Windows2003-3790/inetcore/outlookexpress/wabw/wabapi/ui_abook.c
2020-09-30 16:53:55 +02:00

5594 lines
194 KiB
C

////////////////////////////////////////////////////////////////////////////////////////
//
//
// UI_ABOOK.C - contains code for the Browse mode Overlapped Window address book view
//
// Developers: VikramM 5/96
//
////////////////////////////////////////////////////////////////////////////////////////
#include "_apipch.h"
#include "hotsync.h"
#include "htmlhelp.h"
#include <mirror.h>
extern HINSTANCE ghCommCtrlDLLInst;
extern const LPTSTR lpszRegPositionKeyValueName;
extern BOOL bIsPasteData();
extern HRESULT HrPasteData(LPBWI lpbwi);
extern void AddFolderListToMenu(HMENU hMenu, LPIAB lpIAB);
const static LPTSTR szWABMigRegPathKey = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\wabmig.exe");
const static LPTSTR szWABExeRegPathKey = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\wab.exe");
const LPTSTR szWABMIG = TEXT("wabmig.exe");
const LPTSTR szWABExe = TEXT("wab.exe");
const TCHAR szEXPORT[] = TEXT("/export");
const TCHAR szIMPORT[] = TEXT("/import");
const TCHAR szEXPORTwProfileParam[]=TEXT("/export+/pid:%s+/file:%s");
const TCHAR szIMPORTwProfileParam[]=TEXT("/import+/pid:%s+/file:%s");
// This struct helps in identifying contact folders and groups and in navigating
// around them
//
void FillTreeView(LPBWI lpbwi, HWND hWndTV, LPSBinary lpsbSelection);
void UpdateTVGroupSelection(HWND hWndTV, LPSBinary lpsbSelectEID);
void GetCurrentSelectionEID(LPBWI lpbwi, HWND hWndTV, LPSBinary * lppsbEID, ULONG * lpulObjectType, BOOL bTopMost);
void ClearTreeViewItems(HWND hWndTV);
void UpdateLV(LPBWI lpbwi);
void UpdateListViewContents(LPBWI lpbwi, LPSBinary lpsbEID, ULONG ulObjectType);
void ViewCurrentGroupProperties(LPBWI lpbwi, LPFILETIME lpftLast);
BOOL bIsFocusOnTV(LPBWI lpbwi);
BOOL bIsSelectedTVContainer(LPBWI lpbwi);
BOOL SplitterHitTest(HWND hWndT, LPARAM lParam);
void DragSplitterBar(LPBWI lpbwi, HWND hwnd, HWND hWndT, LPARAM lParam);
HRESULT FillListFromGroup(LPADRBOOK lpIAB, ULONG cbGroupEntryID, LPENTRYID lpGroupEntryID, LPTSTR lpszName, ULONG cchName, LPRECIPIENT_INFO * lppList);
extern LPIMAGELIST_DESTROY gpfnImageList_Destroy;
// extern LPIMAGELIST_LOADIMAGE gpfnImageList_LoadImage;
extern LPIMAGELIST_LOADIMAGE_A gpfnImageList_LoadImageA;
extern LPIMAGELIST_LOADIMAGE_W gpfnImageList_LoadImageW;
extern ULONG GetToolbarButtonWidth();
void RemoveCurrentGroup(LPBWI lpbwi, HWND hWnd, LPFILETIME lpftLast);
HRESULT RemoveCurrentFolder(LPBWI lpbwi, HWND hWnd, LPFILETIME lpftLast);
void RemoveSelectedItemsFromCurrentGroup(LPBWI lpbwi, HWND hWnd, LPFILETIME lpftLast, BOOL bRemoveFromWAB);
void RemoveSelectedItemsFromListView(HWND hWndLV, LPRECIPIENT_INFO *lppList);
LRESULT ProcessTreeViewMessages(LPBWI lpbwi, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LPFILETIME lpftLast);
#ifdef COLSEL_MENU
BOOL UpdateOptionalColumns( LPBWI lpbwi, ULONG iColumn );
#endif // COLSEL_MENU
// Initial Window Size
#define INIT_WINDOW_W 500
#define INIT_WINDOW_H 375
// Minimum Window Size - presently constrained
#define MIN_WINDOW_W 300
#define MIN_WINDOW_H 200
BOOL fOleInit = FALSE;
//
// Some IDs for the Button Bar
//
// Address Book Window Class Name
LPTSTR g_szClass = TEXT("WABBrowseView");
// Function ProtoTypes
LRESULT CALLBACK AddressBookWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
void CreateAddressBookChildren(LPBWI lpbwi, HWND hWnd);
void ResizeAddressBookChildren(LPBWI lpbwi, HWND hWndParent);
HWND CreateListViewAddrBook (HWND hWndParent);
void InitChildren(LPBWI lpbwi, HWND hWnd);
void SetListViewStyle(LPBWI lpbwi, int MenuID);
void CleanUpGlobals(LPBWI lpbwi);
HRESULT HrFolderProperties(HWND hWndParent, LPIAB lpIAB, LPSBinary lpsbEID, LPWABFOLDER lpParentFolder, LPSBinary lpsbNew);
//void TabToNextItem();
LRESULT ProcessListViewMessages(LPBWI lpbwi, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT EnforceMinSize(LPBWI lpbwi, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK SubClassedProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
void RefreshListView(LPBWI lpbwi, LPFILETIME lpftLast);
STDAPI_(BOOL) FindABWindowProc( HWND hWndToLookAt, LPARAM lParam);
void UpdateSortMenus(LPBWI lpbwi, HWND hWnd);
void UpdateToolbarAndMenu(LPBWI lpbwi);
void UpdatePrintMenu(HWND hWnd);
void UpdateOutlookMenus(HWND hWnd);
void UpdateCustomColumnMenuText(HWND hWnd);
void UpdateViewFoldersMenu(LPBWI lpbwi, HWND hWnd);
void UpdateSwitchUsersMenu(HWND hWnd, LPIAB lpIAB);
//LPFNABSDI lpfnAccelerateMessages;
BOOL STDMETHODCALLTYPE fnAccelerateMessages(ULONG_PTR ulUIParam, LPVOID lpvmsg);
void SetPreviousSessionPosition(LPBWI lpbwi, HWND hWnd, HWND hWndLV, HWND hWndTB, HWND hWndSB);
void SaveCurrentPosition(LPBWI lpbwi, HWND hWnd, HWND hWndLV, HWND hWndTB, HWND hWndSB);
void Handle_WM_MENSELECT (LPBWI lpbwi, UINT message, WPARAM uParam, LPARAM lParam );
void Handle_WM_INITMENUPOPUP(HWND hWnd, LPBWI lpbwi, UINT message, WPARAM uParam, LPARAM lParam );
void UpdateTooltipTextBuffer(LPBWI lpbwi, int nItem);
void InitMultiLineToolTip(LPBWI lpbwi, HWND hWndParent);
void FillTooltipInfo(LPBWI lpbwi, LPTOOLINFO lpti);
int HitTestLVSelectedItem(LPBWI lpbwi);
BOOL bCheckIfOnlyGroupsSelected(HWND hWndLV);
void DestroyImageLists(LPBWI lpbwi);
#define WAB_TOOLTIP_TIMER_ID 888
#define WAB_TOOLTIP_TIMER_TIMEOUT 750 // milliseconds
HRESULT HrExportWAB(HWND hWnd, LPBWI lpbwi);
void HrShowOptionsDlg(HWND hWndParent);
//$$ extern void UIOLEUninit();
void UIOLEUninit()
{
if(fOleInit)
{
OleUninitialize();
fOleInit = FALSE;
}
}
void UIOLEInit()
{
if(!fOleInit)
{
OleInitialize(NULL);
fOleInit = TRUE;
}
}
//$$
//
// LocalFreeSBinary - frees a locally alloced SBinary struct
//
//
void LocalFreeSBinary(LPSBinary lpsb)
{
if(lpsb)
{
if(lpsb->lpb)
LocalFree(lpsb->lpb);
LocalFree(lpsb);
}
}
//$$
/*----------------------------------------------------------------------*/
//
// RunWABApp - runs the import-export tool based on the registered path
// if regesitered path is not found, shell execs ...
//
/*----------------------------------------------------------------------*/
void RunWABApp(HWND hWnd, LPTSTR szKey, LPTSTR szExeName, LPTSTR szParam)
{
TCHAR szPath[MAX_PATH];
TCHAR szPathExpand[MAX_PATH];
DWORD dwType = 0;
ULONG cbData = CharSizeOf(szPath);
HKEY hKey = NULL;
LONG lRes = 0;
*szPath = '\0';
*szPathExpand = '\0';
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_READ, &hKey))
lRes = RegQueryValueEx( hKey, TEXT(""), NULL, &dwType, (LPBYTE) szPath, &cbData);
if (REG_EXPAND_SZ == dwType)
{
ExpandEnvironmentStrings(szPath, szPathExpand, CharSizeOf(szPathExpand));
StrCpyN(szPath, szPathExpand, ARRAYSIZE(szPath));
}
if(hKey) RegCloseKey(hKey);
if(!lstrlen(szPath))
StrCpyN(szPath, szExeName, ARRAYSIZE(szPath));
ShellExecute(hWnd, TEXT("open"), szPath, szParam, NULL, SW_SHOWNORMAL);
}
//$$
/*----------------------------------------------------------------------*/
//
// StatusBarMessage - puts a message in the status bar
//
/*----------------------------------------------------------------------*/
void StatusBarMessage(LPBWI lpbwi, LPTSTR lpsz)
{
SetWindowText(bwi_hWndSB, lpsz);
UpdateWindow(bwi_hWndSB);
return;
}
//$$
/*----------------------------------------------------------------------*/
//
// ShowLVCountinStatusBar - puts a message in the status bar
//
/*----------------------------------------------------------------------*/
void ShowLVCountinStatusBar(LPBWI lpbwi)
{
TCHAR sz[MAX_UI_STR];
TCHAR szString[MAX_UI_STR];
LoadString(hinstMapiX, idsStatusBarCount, szString, ARRAYSIZE(szString));
wnsprintf(sz, ARRAYSIZE(sz), szString, ListView_GetItemCount(bwi_hWndListAB));
StatusBarMessage(lpbwi, sz);
return;
}
//$$*------------------------------------------------------------------------
//| IAddrBook::Advise::OnNotify handler
//|
//*------------------------------------------------------------------------
ULONG AdviseOnNotify(LPVOID lpvContext, ULONG cNotif, LPNOTIFICATION lpNotif)
{
LPBWI lpbwi = (LPBWI) lpvContext;
DebugTrace( TEXT("=== AdviseOnNotify ===\n"));
if(bwi_bDeferNotification)
{
LPPTGDATA lpPTGData=GetThreadStoragePointer();
if(!pt_bIsWABOpenExSession)
{
DebugTrace( TEXT("=== Advise Defered ===\n"));
bwi_bDeferNotification = FALSE;
return S_OK;
}
}
if(!bwi_bDontRefreshLV)
{
DebugTrace( TEXT("=== Calling RefreshListView ===\n"));
HrGetWABProfiles(bwi_lpIAB);
RefreshListView(lpbwi, NULL);
}
return S_OK;
}
/*
-
- GetSelectedUserFolder - returns a pointer to the selected User Folder if any
* If the selection is on a sub-folder, gets the parent User folder for that folder
*
*/
LPWABFOLDER GetSelectedUserFolder(LPBWI lpbwi)
{
ULONG ulObjectType = 0;
LPSBinary lpsbEID = NULL;
LPWABFOLDER lpFolder = NULL;
//if(bIsSelectedTVContainer(lpbwi))
{
GetCurrentSelectionEID(lpbwi, bwi_hWndTV, &lpsbEID, &ulObjectType, TRUE);
if(bIsWABSessionProfileAware(bwi_lpIAB))
lpFolder = FindWABFolder(bwi_lpIAB, lpsbEID, NULL, NULL);
}
LocalFreeSBinary(lpsbEID);
return (lpFolder && lpFolder->lpProfileID) ? lpFolder : NULL;
}
/*
- RemoveUpdateSelection - Updates the selected TV Item when a deletion is done
-
*
*/
void RemoveUpdateSelection(LPBWI lpbwi)
{
HTREEITEM hItem = bwi_hti ? bwi_hti : TreeView_GetSelection(bwi_hWndTV);
if(TreeView_GetParent(bwi_hWndTV, hItem))
hItem = TreeView_GetParent(bwi_hWndTV, hItem);
else
hItem = TreeView_GetNextSibling(bwi_hWndTV, hItem);
if(!hItem)
hItem = TreeView_GetRoot(bwi_hWndTV);
TreeView_SelectItem(bwi_hWndTV, hItem);
bwi_hti = NULL;
}
/*
- CreateWindowTitle - if we don't have a passed in caption, create a title
- If there is a current user, add the user's name to the title
- Returns LocalAlloced stuff that needs to be freed
-
*/
LPTSTR CreateWindowTitle(LPIAB lpIAB)
{
LPTSTR lpTitle = NULL;
TCHAR szTitle[MAX_PATH];
LPTSTR lpsz = NULL;
szTitle[0] = 0;
if(bIsThereACurrentUser(lpIAB))
{
LPTSTR lpsz = lpIAB->szProfileName;
LoadString(hinstMapiX, idsCaptionWithText, szTitle, ARRAYSIZE(szTitle));
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING |FORMAT_MESSAGE_ARGUMENT_ARRAY,
szTitle, 0, 0, (LPTSTR) &lpTitle, 0, (va_list *)&lpsz);
}
if(!lpTitle || !lstrlen(lpTitle))
{
DWORD cchSize = (lstrlen(szTitle)+1);
LoadString(hinstMapiX, IDS_ADDRBK_CAPTION, szTitle, ARRAYSIZE(szTitle));
if(lpTitle = LocalAlloc(LMEM_ZEROINIT, sizeof(TCHAR)*cchSize))
StrCpyN(lpTitle, szTitle, cchSize);
}
return lpTitle;
}
//$$*------------------------------------------------------------------------
//| Main call to create, activate address book overlapped-window
//|
//*------------------------------------------------------------------------
HWND hCreateAddressBookWindow(LPADRBOOK lpAdrBook, HWND hWndParent, LPADRPARM lpAdrParms)
{
WNDCLASS wc;
HWND hWnd = NULL;
HMENU hMenu = NULL;
LPPTGDATA lpPTGData=GetThreadStoragePointer();
LPBWI lpbwi = NULL;
LPTSTR lpTitle = NULL;
LPIAB lpIAB = (LPIAB)lpAdrBook;
LPTSTR szCaption = (lpAdrParms->ulFlags & MAPI_UNICODE) ? // <note> assumes UNICODE defined
(LPWSTR)lpAdrParms->lpszCaption :
ConvertAtoW((LPSTR)lpAdrParms->lpszCaption);
DWORD dwExStyle = WS_EX_NOPARENTNOTIFY | WS_EX_CONTROLPARENT;
if(IS_BIDI_LOCALIZED_SYSTEM())
{
dwExStyle |= RTL_MIRRORED_WINDOW;
}
// if no common control, exit
if (NULL == ghCommCtrlDLLInst)
goto out;
//
// We want each thread to only have one address book window - so we do an
// enum thread windows and look for our address book window
// If we find it - we set focus to it - if we dont find it
// we go ahead and create a new one for this thread ...
//
// Is this window we found related to my thread?
EnumThreadWindows( GetCurrentThreadId(),
FindABWindowProc,
(LPARAM) &hWnd);
if (IsWindow(hWnd))
{
//Perhaps the window was hidden .. show it
//if (!IsWindowVisible(hWnd))
// ShowWindow(hWnd,SW_NORMAL | SW_RESTORE);
// SetWindowPos(hWnd, HWND_TOP,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
if(IsWindowEnabled(hWnd))
{
SetActiveWindow(hWnd);
// [PaulHi] 12/1/98 Raid #58527
// The window may also be minimized.
if ( IsIconic(hWnd) )
ShowWindow(hWnd, SW_RESTORE);
}
else
{
HWND hWndC = GetLastActivePopup(hWnd);
SetForegroundWindow(hWndC);
}
{
// The previous instance of the Dialog might have had a different caption
// so we update the caption
LPBWI lpbwi = (LPBWI) GetWindowLongPtr(hWnd, GWLP_USERDATA);
if(szCaption)
SetWindowText(hWnd,szCaption);
if(lpbwi)
{
bwi_bDontRefreshLV = TRUE;
RefreshListView(lpbwi,NULL);
bwi_bDontRefreshLV = FALSE;
}
goto out;
}
}
lpbwi = LocalAlloc(LMEM_ZEROINIT, sizeof(BWI));
if(!lpbwi)
{
DebugTrace( TEXT("LocalAlloc failed\n"));
goto out;
}
TrimSpaces(szCaption);
lpTitle = (szCaption && lstrlen(szCaption)) ? szCaption : CreateWindowTitle(lpIAB);
//
// if we're here, we didnt succeed in finding or displaying the window
//
wc.style = 0L;
wc.lpfnWndProc = AddressBookWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hinstMapiXWAB; //NULL;
wc.hIcon = LoadIcon(hinstMapiX,MAKEINTRESOURCE(IDI_ICON_ABOOK));;
wc.hCursor = NULL;
wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClass;
if(!RegisterClass(&wc))
{
DebugPrintError(( TEXT("Attempt to register class failed: %d!\n"),GetLastError()));
}
// In windows95 there is no way of telling wether or not the WindowClass is
// already registered. Hence we should go ahead and try to create the window
// anyway making sure to trap the errors.
// (The above is really needed for Athena - which runs on the system Explorer thread
// and never really shuts down till the system is shut off - as a result the WndClass
// registration above would continue to exist and RegisterClass would fail due
// to TEXT("incorrect parameters") .. so we let this play on ..
hMenu = LoadMenu(hinstMapiX, MAKEINTRESOURCE(IDR_MENU_AB));
if (!hMenu)
{
DebugPrintError(( TEXT("LoadMenu failed: %x\n"),GetLastError()));
goto out;
}
// Clean any garbage from previous sessions
CleanUpGlobals(lpbwi);
bwi_lpfnDismiss = NULL;
bwi_lpvDismissContext = NULL;
#ifndef WIN16 // WIN16FF : disable until ldap16.dll is available.
if (bwi_lpAdrBook)
{
ReleasePropertyStore(bwi_lpIAB->lpPropertyStore);
bwi_lpAdrBook->lpVtbl->Release(bwi_lpAdrBook);
bwi_lpAdrBook = NULL;
bwi_lpIAB = NULL;
pt_lpIAB = NULL;
}
#else
bwi_lpAdrBook = NULL;
bwi_lpIAB = NULL;
#endif // !WIN16
// we need this pointer ....
if (!bwi_lpAdrBook)
{
bwi_lpAdrBook = lpAdrBook;
bwi_lpIAB = (LPIAB)bwi_lpAdrBook;
UlAddRef(bwi_lpAdrBook);
OpenAddRefPropertyStore(NULL, bwi_lpIAB->lpPropertyStore);
pt_lpIAB = lpAdrBook;
}
HrAllocAdviseSink(&AdviseOnNotify, (LPVOID) lpbwi, &(bwi_lpAdviseSink));
DebugTrace( TEXT("WAB Window Title is \"%s\"\n"),lpTitle?lpTitle:szEmpty);
{
if(IS_BIDI_LOCALIZED_SYSTEM())
{
dwExStyle |= RTL_MIRRORED_WINDOW;
}
hWnd = CreateWindowEx( dwExStyle,
g_szClass,
lpTitle ? lpTitle : szEmpty,
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
CW_USEDEFAULT,
CW_USEDEFAULT,
INIT_WINDOW_W,
INIT_WINDOW_H,
NULL,
hMenu,
hinstMapiXWAB,
(LPVOID)lpbwi);
if (!hWnd)
{
DebugPrintError(( TEXT("Ok. CreateWindowEx failed. Ugh.\n")));
if (bwi_lpAdrBook)
{
ReleasePropertyStore(bwi_lpIAB->lpPropertyStore);
bwi_lpAdrBook->lpVtbl->Release(bwi_lpAdrBook);
bwi_lpAdrBook = NULL;
bwi_lpIAB = NULL;
}
goto out;
}
// Set up the menu markers on the sort menus ...
SortListViewColumn(bwi_lpIAB, bwi_hWndListAB, colDisplayName, &bwi_SortInfo, TRUE);
SetColumnHeaderBmp(bwi_hWndListAB, bwi_SortInfo);
// Update folders before redoing any other menu since removing folders
// changes the order number of the other items
UpdateSortMenus(lpbwi, hWnd);
// **IMPORTANT**
// These 4 calls are position based removals so order of calling them functions is important
UpdateSwitchUsersMenu(hWnd, bwi_lpIAB);
UpdateViewFoldersMenu(lpbwi, hWnd);
UpdatePrintMenu(hWnd);
UpdateOutlookMenus(hWnd);
//////////////////////////////////////////////////////////////////////////////////
UpdateCustomColumnMenuText(hWnd);
IF_WIN32(ShowWindow(hWnd,SW_SHOWDEFAULT);)
IF_WIN16(ShowWindow(hWnd,SW_SHOW);)
if(lpAdrParms->ulFlags & DIALOG_SDI)
{
lpAdrParms->lpfnABSDI = &fnAccelerateMessages;
bwi_lpfnDismiss = lpAdrParms->lpfnDismiss;
bwi_lpvDismissContext = lpAdrParms->lpvDismissContext;
}
// load the accelrator table ...
pt_hAccTable = LoadAccelerators(hinstMapiX, TEXT("WabUIAccel"));
// repainting everything ...
RedrawWindow( hWnd,
NULL,
NULL,
RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);
//populate the window
bwi_bDontRefreshLV = TRUE;
RefreshListView(lpbwi,NULL);
bwi_bDontRefreshLV = FALSE;
}
out:
if(lpTitle != szCaption)
LocalFree(lpTitle);
if(szCaption != lpAdrParms->lpszCaption)
LocalFreeAndNull(&szCaption);
return (hWnd);
}
#if WINVER < 0X0500
#define WS_EX_LAYOUTRTL 0x00400000L // Right to left mirroring
#endif // WS_EX_LAYOUTRTL
//$$
//
//
void ShowToolbarItemMenu(LPBWI lpbwi, HWND hWndTools, int tbitem, int lvtb)
{
// We're going to pop up the Action sub-menu - need to align it
// neatly with the bottom of the toolbar
RECT rc = {0}, rcButton = {0};
LPARAM lp;
SendMessage(hWndTools, TB_GETITEMRECT, (WPARAM)tbitem, (LPARAM)&rcButton);
GetWindowRect(bwi_hWndBB, &rc);
lp = MAKELPARAM((GetWindowLong(bwi_hWndBB, GWL_EXSTYLE) & WS_EX_LAYOUTRTL)? rc.right - rcButton.left : rc.left + rcButton.left, rc.top + rcButton.bottom);
ShowLVContextMenu( lvtb, bwi_hWndListAB, NULL, lp, NULL, bwi_lpAdrBook, bwi_hWndTV);
}
//$$
//*------------------------------------------------------------------------
//| AddressBookWndProx:
//|
//*------------------------------------------------------------------------
LRESULT CALLBACK AddressBookWndProc(HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
static UINT uTimer = 0;
static FILETIME ftLast = {0};
// HBRUSH to draw STATIC control's background
IF_WIN16(static HBRUSH hBrushBack;)
static BOOL bMouseDrag = FALSE;
LPBWI lpbwi = (LPBWI) GetWindowLongPtr(hWnd, GWLP_USERDATA);
LPPTGDATA lpPTGData=GetThreadStoragePointer();
switch(uMsg)
{
// OE5 HACK. Do not use these WM_USER values in the WAB wndproc
// OE subclasses the WAB to do some modal voodoo in common\ipab.cpp
// if needs to send these private messages.
// case WM_USER + 10666:
// case WM_USER + 10667:
//break;
#ifdef HM_GROUP_SYNCING
case WM_USER_SYNCGROUPS:
// We don't want the user to have to select the HM account for both passes, so use
// the TLS stored account ID if it is available.
HrSynchronize(hWnd, bwi_lpAdrBook, lpPTGData->lptszHMAccountId, TRUE); // Sync group contacts
break;
#endif
case WM_INITMENUPOPUP:
Handle_WM_INITMENUPOPUP(hWnd, lpbwi, uMsg, wParam, lParam);
break;
case WM_MENUSELECT:
Handle_WM_MENSELECT(lpbwi, uMsg, wParam, lParam);
break;
case WM_MOUSEMOVE:
if(SplitterHitTest(bwi_hWndSplitter, lParam))
SetCursor(LoadCursor(NULL, IDC_SIZEWE));
break;
case WM_LBUTTONDOWN:
if(SplitterHitTest(bwi_hWndSplitter, lParam))
{
DragSplitterBar(lpbwi, hWnd, bwi_hWndSplitter, lParam);
}
break;
case WM_COMMAND:
{
switch(GET_WM_COMMAND_ID(wParam, lParam))
{
default:
if(GET_WM_COMMAND_ID(wParam, lParam) >= IDM_VIEW_FOLDERS1 &&
GET_WM_COMMAND_ID(wParam, lParam) <= IDM_VIEW_FOLDERS1 + MAX_VIEW_FOLDERS)
{
LPWABFOLDER lpFolder = bwi_lpIAB->lpWABFolders;
if(lpFolder)
{
int nCmdID = GET_WM_COMMAND_ID(wParam, lParam);
LPSBinary lpsb = NULL;
while(lpFolder)
{
if(nCmdID == lpFolder->nMenuCmdID)
break;
lpFolder = lpFolder->lpNext;
}
if(lpFolder)
{
if(!HR_FAILED(HrUpdateFolderInfo((bwi_lpIAB), &lpFolder->sbEID,
FOLDER_UPDATE_SHARE, !lpFolder->bShared, NULL)))
{
HrGetWABProfiles((bwi_lpIAB));
}
if(!IsWindowVisible(bwi_hWndTV))
PostMessage(hWnd, WM_COMMAND, (WPARAM) IDM_VIEW_GROUPSLIST, 0);
}
if(bwi_lpUserFolder)
bwi_lpUserFolder = NULL;
//UpdateViewFoldersMenu(lpbwi, hWnd);
// Refresh the UI
GetCurrentSelectionEID(lpbwi, bwi_hWndTV, &lpsb, NULL, FALSE);
bwi_bDontRefreshLV = TRUE;
RefreshListView(lpbwi,&ftLast);
UpdateLV(lpbwi);
UpdateTVGroupSelection(bwi_hWndTV, lpsb);
bwi_bDontRefreshLV = FALSE;
LocalFreeSBinary(lpsb);
}
}
#ifdef COLSEL_MENU
else if ((GET_WM_COMMAND_ID(wParam, lParam) > IDR_MENU_LVCONTEXTMENU_COLSEL) &&
(GET_WM_COMMAND_ID(wParam, lParam) <= (IDR_MENU_LVCONTEXTMENU_COLSEL + MAX_VIEW_COLSEL)))
{
BOOL rVal = FALSE;
TCHAR szBuf[MAX_PATH];
ULONG iCol = lpbwi->iSelColumn;
ULONG ulCmdId = GET_WM_COMMAND_ID(wParam, lParam);
ULONG iTagSel = (ulCmdId - IDR_MENU_LVCONTEXTMENU_COLSEL - 1);
LONG lr = 0;
HMENU hMenu = LoadMenu(hinstMapiX, MAKEINTRESOURCE(IDR_MENU_LVCONTEXTMENU_COLSEL));
HMENU hSubMenu = GetSubMenu(hMenu, 0);
MENUITEMINFO mii;
if( hMenu && hSubMenu )
{
mii.fMask = MIIM_TYPE;
mii.dwTypeData = szBuf;
mii.cch = CharSizeOf( szBuf );
mii.cbSize = sizeof (MENUITEMINFO);
if ( !GetMenuItemInfo( hSubMenu, iTagSel, TRUE, &mii) )
{
DebugTrace( TEXT("cannot get info : %d\n"), GetLastError() );
rVal = TRUE;
}
else
{
if( iCol == colHomePhone || iCol == colOfficePhone)
{
if( iCol == colHomePhone )
{
PR_WAB_CUSTOMPROP1 = MenuToPropTagMap[iTagSel];
StrCpyN(szCustomProp1, szBuf, ARRAYSIZE(szCustomProp1));
UpdateOptionalColumns( lpbwi, colHomePhone );
}
else
{
PR_WAB_CUSTOMPROP2 = MenuToPropTagMap[iTagSel];
StrCpyN(szCustomProp2, szBuf, ARRAYSIZE(szCustomProp2));
UpdateOptionalColumns( lpbwi, colOfficePhone );
}
UpdateLV( lpbwi );
UpdateSortMenus(lpbwi, hWnd);
UpdateCustomColumnMenuText(hWnd);
}
}
}
else
{
DebugTrace( TEXT("LoadMenu failed: %d\n"), GetLastError());
rVal = TRUE;
}
DestroyMenu(hMenu);
return rVal;
}
#endif //COLSEL_MENU
else
{
LRESULT fRet = FALSE;
bwi_hti = NULL;
bwi_bDontRefreshLV = TRUE;
fRet = ProcessActionCommands(bwi_lpIAB, bwi_hWndListAB,
hWnd, uMsg, wParam, lParam);
bwi_bDontRefreshLV = FALSE;
return fRet;
}
break;
case IDM_EDIT_SETME:
{
SBinary sb = {0};
HrSetMeObject(bwi_lpAdrBook, MAPI_DIALOG, sb, (ULONG_PTR)hWnd);
}
break;
case IDM_FILE_EXIT:
SendMessage(hWnd,WM_CLOSE,0,0L);
return 0;
break;
case IDC_ABOOK_STATIC_QUICK_FIND:
SetFocus(bwi_hWndEditQF);
break;
case IDC_BB_NEW:
ShowToolbarItemMenu(lpbwi, bwi_hWndTools, tbNew, lvToolBarNewEntry);
break;
case IDC_BB_ACTION:
// OE 63674
// When the Print button is hidden (thanks to idsLangPrintingOn==0)
// The enumeration item tbAction is off by 1
ShowToolbarItemMenu(lpbwi, bwi_hWndTools, bPrintingOn ? tbAction : tbAction - 1, lvToolBarAction);
break;
case IDM_FILE_SENDMAIL:
bwi_hti = NULL; // if this wasnt a context-initiated action, dont trust the hti setting
case IDM_LVCONTEXT_SENDMAIL:
bwi_bDontRefreshLV = TRUE;
/*
if(bIsFocusOnTV(lpbwi) && !bIsSelectedTVContainer(lpbwi))
{
LPSBinary lpsbEID = NULL;
GetCurrentSelectionEID(lpbwi, bwi_hWndTV, &lpsbEID, NULL, FALSE);
if(lpsbEID && lpsbEID->lpb)
{
HrSendMailToSingleContact(hWnd, bwi_lpIAB, lpsbEID->cb, (LPENTRYID)lpsbEID->lpb);
LocalFreeSBinary(lpsbEID);
}
}
else
*/
HrSendMailToSelectedContacts(bwi_hWndListAB, bwi_lpAdrBook, 0);
bwi_hti = NULL;
bwi_bDontRefreshLV = FALSE;
break;
case IDC_BB_DELETE:
case IDM_FILE_DELETE:
bwi_hti = NULL; // if this wasnt a context-initiated action, dont trust the hti setting
case IDM_LVCONTEXT_DELETE:
bwi_bDontRefreshLV = TRUE;
// if focus is on the treeview, remove the group from the treeview
if(bIsFocusOnTV(lpbwi))
{
if(!bIsSelectedTVContainer(lpbwi))
{
RemoveCurrentGroup(lpbwi, hWnd, &ftLast);
bwi_bDeferNotification = TRUE;
SetFocus(bwi_hWndTV);
}
else
{
if(!HR_FAILED(RemoveCurrentFolder(lpbwi, hWnd, &ftLast)))
{
UpdateLV(lpbwi);
//UpdateViewFoldersMenu(lpbwi, hWnd);
SetFocus(bwi_hWndTV);
bwi_bDeferNotification = TRUE;
}
}
bwi_hti = NULL;
}
else
{
// Focus is on the ListView
// If we're looking at the root AB - remove from addressbook
// If we're looking at some group, remove entries from group
bwi_hti = NULL; // if this wasnt a context-initiated action on the tree view, dont trust the hti setting
if(!bIsSelectedTVContainer(lpbwi))
{
// a group is selected .. remove from the group .. unless
// the shift key is pressed which means remove from the
// address book
if(GetKeyState(VK_SHIFT) & 0x80)
RemoveSelectedItemsFromCurrentGroup(lpbwi, hWnd, &ftLast, TRUE);
else
RemoveSelectedItemsFromCurrentGroup(lpbwi, hWnd, &ftLast, FALSE);
bwi_hti = NULL;
bwi_bDontRefreshLV = TRUE;
RefreshListView(lpbwi,&ftLast);
bwi_bDontRefreshLV = FALSE;
bwi_bDeferNotification = TRUE;
}
else // Container selected - remove selected items from the container
{
DeleteSelectedItems(bwi_hWndListAB, (LPADRBOOK)bwi_lpAdrBook, bwi_lpIAB->lpPropertyStore->hPropertyStore, &ftLast);
bwi_hti = NULL;
bwi_bDontRefreshLV = TRUE;
RefreshListView(lpbwi,&ftLast);
bwi_bDontRefreshLV = FALSE;
bwi_bDeferNotification = TRUE;
}
SetFocus(bwi_hWndListAB);
}
bwi_hti = NULL;
UpdateToolbarAndMenu(lpbwi);
bwi_bDontRefreshLV = FALSE;
return 0;
break;
case IDM_FILE_NEWFOLDER:
bwi_hti = NULL; // if this wasnt a context-initiated action, dont trust the hti setting
case IDM_LVCONTEXT_NEWFOLDER:
bwi_bDontRefreshLV = TRUE;
{
LPWABFOLDER lpParent = GetSelectedUserFolder(lpbwi);
LPSBinary lpNew = NULL;
SBinary sbNewFolder = {0}, sbParent = {0};
if(lpParent)
SetSBinary(&sbParent, lpParent->sbEID.cb, lpParent->sbEID.lpb);
HrFolderProperties(hWnd, bwi_lpIAB, NULL, lpParent, &sbNewFolder);
if(sbNewFolder.lpb)
lpNew = &sbNewFolder;
else if(lpParent)
lpNew = &sbParent;
//UpdateViewFoldersMenu(lpbwi, hWnd);
if(!IsWindowVisible(bwi_hWndTV))
PostMessage(hWnd, WM_COMMAND, (WPARAM) IDM_VIEW_GROUPSLIST, 0);
HrGetWABProfiles(bwi_lpIAB);
RefreshListView(lpbwi, NULL);
if(lpNew && lpNew->cb)
UpdateTVGroupSelection(bwi_hWndTV, lpNew);
LocalFreeAndNull((LPVOID *) (&(sbParent.lpb)));
LocalFreeAndNull((LPVOID *) (&(sbNewFolder.lpb)));
}
bwi_bDontRefreshLV = FALSE;
bwi_bDeferNotification = TRUE;
bwi_hti = NULL;
break;
case IDM_FILE_NEWGROUP:
bwi_hti = NULL; // if this wasnt a context-initiated action, dont trust the hti setting
case IDM_LVCONTEXT_NEWGROUP:
//case IDC_BB_NEW_GROUP:
{
ULONG cbEID = 0;
LPENTRYID lpEID = NULL;
HRESULT hr = S_OK;
bwi_bDontRefreshLV = TRUE;
hr = AddNewObjectToListViewEx(bwi_lpAdrBook, bwi_hWndListAB, bwi_hWndTV, bwi_hti,
NULL, MAPI_DISTLIST,
&bwi_SortInfo, &bwi_lpContentsList, &ftLast,
&cbEID, &lpEID);
if(hr != MAPI_E_USER_CANCEL)
{
bwi_hti = NULL;
RefreshListView(lpbwi,&ftLast);
if(cbEID && lpEID && IsWindowVisible(bwi_hWndTV))
{
SBinary sbEID = {cbEID, (LPBYTE)lpEID };
UpdateTVGroupSelection(bwi_hWndTV,&sbEID);
FreeBufferAndNull(&lpEID);
}
}
bwi_bDontRefreshLV = FALSE;
//bwi_bDeferNotification = TRUE;
UpdateToolbarAndMenu(lpbwi);
}
break;
case IDM_FILE_NEWCONTACT:
bwi_hti = NULL; // if this wasnt a context-initiated action, dont trust the hti setting
case IDM_LVCONTEXT_NEWCONTACT:
bwi_bDontRefreshLV = TRUE;
AddNewObjectToListViewEx( bwi_lpAdrBook, bwi_hWndListAB, bwi_hWndTV, bwi_hti,
NULL, MAPI_MAILUSER,
&bwi_SortInfo, &bwi_lpContentsList, &ftLast,NULL,NULL);
//RefreshListView(lpbwi,&ftLast);
bwi_hti = NULL;
//bwi_bDeferNotification = TRUE;
bwi_bDontRefreshLV = FALSE;
UpdateToolbarAndMenu(lpbwi);
break;
case IDM_TOOLS_OPTIONS:
HrShowOptionsDlg(hWnd);
break;
case IDM_TOOLS_SYNCHRONIZE_NOW:
#ifdef HM_GROUP_SYNCING
HrSynchronize(hWnd, bwi_lpAdrBook, NULL, FALSE); // Sync mail contacts
#else
HrSynchronize(hWnd, bwi_lpAdrBook, NULL);
#endif
break;
case IDM_FILE_DIRECTORY_SERVICE:
HrShowDirectoryServiceModificationDlg(hWnd, bwi_lpIAB);
break;
case IDC_BB_PRINT:
case IDM_FILE_PRINT:
if(bPrintingOn)
{
TCHAR szBuf[MAX_PATH];
bwi_bDontRefreshLV = TRUE;
LoadString(hinstMapiX, idsPrintStatusBarMessage, szBuf, ARRAYSIZE(szBuf));
StatusBarMessage(lpbwi, szBuf);
HrPrintItems(hWnd, bwi_lpAdrBook, bwi_hWndListAB, bwi_SortInfo.bSortByLastName);
ShowLVCountinStatusBar(lpbwi);
bwi_hti = NULL;
bwi_bDontRefreshLV = FALSE;
}
break;
case IDM_EDIT_COPY:
bwi_hti = NULL; // if this wasnt a context-initiated action, dont trust the hti setting
case IDM_LVCONTEXT_COPY:
{
LPIWABDATAOBJECT lpIWABDataObject = NULL;
bwi_bDontRefreshLV = TRUE;
HrCreateIWABDataObject((LPVOID)lpbwi, bwi_lpAdrBook, bwi_hWndListAB, &lpIWABDataObject,
TRUE,bCheckIfOnlyGroupsSelected(bwi_hWndListAB));
if(lpIWABDataObject)
{
bwi_lpIWABDragDrop->m_bSource = TRUE;
OleSetClipboard((LPDATAOBJECT) lpIWABDataObject);
bwi_lpIWABDragDrop->m_bSource = FALSE;
lpIWABDataObject->lpVtbl->Release(lpIWABDataObject);
}
//HrCopyItemDataToClipboard(hWnd, bwi_lpAdrBook, bwi_hWndListAB);
bwi_hti = NULL;
bwi_bDontRefreshLV = FALSE;
}
break;
case IDM_EDIT_PASTE:
bwi_hti = NULL; // if this wasnt a context-initiated action, dont trust the hti setting
case IDM_LVCONTEXT_PASTE:
{
LPDATAOBJECT lpDataObject = NULL;
bwi_bDontRefreshLV = TRUE;
if(bIsPasteData())
{
if(S_OK == HrPasteData(lpbwi))
UpdateLV(lpbwi);
}
//HrCopyItemDataToClipboard(hWnd, bwi_lpAdrBook, bwi_hWndListAB);
bwi_hti = NULL;
bwi_bDontRefreshLV = FALSE;
}
break;
case IDC_BB_FIND:
case IDM_EDIT_FIND:
bwi_hti = NULL; // if this wasnt a context-initiated action, dont trust the hti setting
case IDM_LVCONTEXT_FIND:
bwi_bDontRefreshLV = TRUE;
HrShowSearchDialog((LPADRBOOK) bwi_lpAdrBook,
bwi_hWndAB,
(LPADRPARM_FINDINFO) NULL,
(LPLDAPURL) NULL,
&(bwi_SortInfo));
bwi_hti = NULL;
RefreshListView(lpbwi,&ftLast);
bwi_bDeferNotification = TRUE;
bwi_bDontRefreshLV = FALSE;
UpdateToolbarAndMenu(lpbwi);
SetFocus(bwi_hWndListAB);
break;
case IDM_EDIT_SELECTALL:
{
int index = 0;
int iTotal = ListView_GetItemCount(bwi_hWndListAB);
if (iTotal > 0)
{
for(index=0;index<iTotal;index++)
{
ListView_SetItemState ( bwi_hWndListAB, // handle to listview
index, // index to listview item
LVIS_SELECTED, // item state
LVIS_SELECTED); // mask
}
}
}
break;
case IDM_HELP_ADDRESSBOOKHELP:
WABHtmlHelp(hWnd, TEXT("%SYSTEMROOT%\\help\\wab.chm>iedefault"),
HH_DISPLAY_TOPIC, (DWORD_PTR) (LPCSTR) TEXT("wab_welcome.htm"));
break;
case IDM_HELP_ABOUTADDRESSBOOK:
DialogBox( hinstMapiX,
MAKEINTRESOURCE(IDD_DIALOG_ABOUT),
hWnd,
HelpAboutDialogProc);
break;
case IDM_FILE_SWITCHUSERS:
HrLogonAndGetCurrentUserProfile(hWnd, bwi_lpIAB, TRUE, FALSE);
break;
case IDM_FILE_SHOWALLCONTENTS:
RunWABApp(hWnd, szWABExeRegPathKey, szWABExe, TEXT("/all"));
break;
case IDM_NOTIFY_REFRESHUSER:
{
LPTSTR lpTitle = CreateWindowTitle(bwi_lpIAB);
SetWindowText(hWnd, lpTitle);
LocalFreeAndNull(&lpTitle);
ReadWABCustomColumnProps(bwi_lpIAB);
UpdateOptionalColumns( lpbwi, colHomePhone );
UpdateOptionalColumns( lpbwi, colOfficePhone );
ReadRegistrySortInfo(bwi_lpIAB,&bwi_SortInfo);
RefreshListView(lpbwi, NULL);
if(bIsThereACurrentUser(bwi_lpIAB))
{
LPSBinary lpsbSelection = &bwi_lpIAB->lpWABCurrentUserFolder->sbEID;
UpdateTVGroupSelection(bwi_hWndTV, lpsbSelection);
}
}
break;
case IDM_FILE_PROPERTIES:
// bobn: brianv says we have to take this out...
/*if(bwi_nCount == 2)
{
if( (GetKeyState(VK_CONTROL) & 0x80) &&
(GetKeyState(VK_MENU) & 0x80) &&
(GetKeyState(VK_SHIFT) & 0x80))
{
SCS(hWnd);
break;
}
}
else
bwi_nCount = 0;*/
case IDC_BB_PROPERTIES:
bwi_hti = NULL; // if this wasnt a context-initiated action, dont trust the hti setting
case IDM_LVCONTEXT_PROPERTIES:
bwi_bDontRefreshLV = TRUE;
if(bIsFocusOnTV(lpbwi))
{
ViewCurrentGroupProperties(lpbwi, &ftLast);
bwi_bDeferNotification = TRUE;
}
else
{
HRESULT hr = HrShowLVEntryProperties(bwi_hWndListAB, WAB_ONEOFF_NOADDBUTTON, bwi_lpAdrBook, &ftLast);
bwi_hti = NULL;
if(hr == MAPI_E_OBJECT_CHANGED)
{
bwi_bDeferNotification = TRUE;
// resort the display
SendMessage(bwi_hWndListAB, WM_SETREDRAW, FALSE, 0);
SortListViewColumn(bwi_lpIAB, bwi_hWndListAB, colDisplayName, &bwi_SortInfo, TRUE);
SendMessage(bwi_hWndListAB, WM_SETREDRAW, TRUE, 0);
}
bwi_bDontRefreshLV = FALSE;
return 0;
}
bwi_bDontRefreshLV = FALSE;
break;
case IDM_VIEW_REFRESH:
bwi_bDontRefreshLV = TRUE;
bwi_hti = NULL;
HrGetWABProfiles(bwi_lpIAB);
RefreshListView(lpbwi,&ftLast);
bwi_bDontRefreshLV = FALSE;
return 0;
break;
case IDM_VIEW_STATUSBAR:
if (IsWindowVisible(bwi_hWndSB))
{
//hide it
CheckMenuItem(GetMenu(hWnd),IDM_VIEW_STATUSBAR,MF_BYCOMMAND | MF_UNCHECKED);
ShowWindow(bwi_hWndSB, SW_HIDE);
}
else
{
CheckMenuItem(GetMenu(hWnd),IDM_VIEW_STATUSBAR,MF_BYCOMMAND | MF_CHECKED);
ShowWindow(bwi_hWndSB, SW_NORMAL);
//special case repainting to workaround a repaint bug ...
InvalidateRect(bwi_hWndListAB,NULL,TRUE);
ShowLVCountinStatusBar(lpbwi);
}
ResizeAddressBookChildren(lpbwi, hWnd);
break;
case IDM_VIEW_TOOLBAR:
if (IsWindowVisible(bwi_hWndBB))
{
//hide it
CheckMenuItem(GetMenu(hWnd),IDM_VIEW_TOOLBAR,MF_BYCOMMAND | MF_UNCHECKED);
ShowWindow(bwi_hWndBB, SW_HIDE);
}
else
{
CheckMenuItem(GetMenu(hWnd),IDM_VIEW_TOOLBAR,MF_BYCOMMAND | MF_CHECKED);
ShowWindow(bwi_hWndBB, SW_NORMAL);
//special case repainting to workaround a repaint bug ...
InvalidateRect(bwi_hWndListAB,NULL,TRUE);
InvalidateRect(bwi_hWndTV,NULL,TRUE);
}
ResizeAddressBookChildren(lpbwi, hWnd);
break;
case IDM_VIEW_GROUPSLIST:
if (IsWindowVisible(bwi_hWndTV))
{
//hide it
CheckMenuItem(GetMenu(hWnd),IDM_VIEW_GROUPSLIST,MF_BYCOMMAND | MF_UNCHECKED);
ShowWindow(bwi_hWndTV, SW_HIDE);
ShowWindow(bwi_hWndSplitter, SW_HIDE);
InvalidateRect(bwi_hWndStaticQF, NULL, TRUE);
// If this is a user based session, we want the hidden focus to be on the user's
// folder not on the Shared Contacts
if(bIsThereACurrentUser(bwi_lpIAB))
{
LPSBinary lpsbSelection = &bwi_lpIAB->lpWABCurrentUserFolder->sbEID;
UpdateTVGroupSelection(bwi_hWndTV, lpsbSelection);
}
else
{
// Set the selection to the root address book so we see the file
// contents just as if we dont have a treeview at all
HTREEITEM hItem = TreeView_GetSelection(bwi_hWndTV);
HTREEITEM hRoot = TreeView_GetRoot(bwi_hWndTV);
if(hItem != hRoot)
TreeView_SelectItem(bwi_hWndTV, hRoot);
}
}
else
{
CheckMenuItem(GetMenu(hWnd),IDM_VIEW_GROUPSLIST,MF_BYCOMMAND | MF_CHECKED);
ShowWindow(bwi_hWndTV, SW_NORMAL);
ShowWindow(bwi_hWndSplitter, SW_NORMAL);
//special case repainting to workaround a repaint bug ...
//InvalidateRect(bwi_hWndListAB,NULL,TRUE);
//InvalidateRect(bwi_hWndTV,NULL,TRUE);
}
ResizeAddressBookChildren(lpbwi, hWnd);
SaveCurrentPosition(lpbwi, hWnd,bwi_hWndListAB,bwi_hWndBB,bwi_hWndSB);
break;
case IDM_VIEW_SORTBY_DISPLAYNAME:
case IDM_VIEW_SORTBY_EMAILADDRESS:
case IDM_VIEW_SORTBY_BUSINESSPHONE:
case IDM_VIEW_SORTBY_HOMEPHONE:
{
//Assuming the above ids are in sequential order ...
int iCol = LOWORD(wParam) - IDM_VIEW_SORTBY_DISPLAYNAME;
SortListViewColumn(bwi_lpIAB, bwi_hWndListAB, iCol, &bwi_SortInfo, FALSE);
UpdateSortMenus(lpbwi, hWnd);
}
break;
case IDM_VIEW_SORTBY_FIRSTNAME:
bwi_SortInfo.bSortByLastName = FALSE;
goto DoSortMenuStuff;
case IDM_VIEW_SORTBY_LASTNAME:
// bobn: brianv says we have to take this out...
/*if(bwi_nCount == 1)
bwi_nCount++;
else
bwi_nCount = 0;*/
bwi_SortInfo.bSortByLastName = TRUE;
goto DoSortMenuStuff;
case IDM_VIEW_SORTBY_DESCENDING:
bwi_SortInfo.bSortAscending = FALSE;
goto DoSortMenuStuff;
case IDM_VIEW_SORTBY_ASCENDING:
bwi_SortInfo.bSortAscending = TRUE;
DoSortMenuStuff:
SortListViewColumn(bwi_lpIAB, bwi_hWndListAB, 0, &bwi_SortInfo, TRUE);
UpdateSortMenus(lpbwi, hWnd);
break;
// miscellanous styles for the list view control
case IDM_VIEW_LARGEICON:
// bobn: brianv says we have to take this out...
/*if(bwi_nCount == 0)
bwi_nCount++;*/
case IDM_VIEW_SMALLICON:
case IDM_VIEW_LIST:
case IDM_VIEW_DETAILS:
SetListViewStyle(lpbwi, LOWORD(wParam));
CheckMenuRadioItem( GetMenu(hWnd),
IDM_VIEW_LARGEICON,
IDM_VIEW_DETAILS,
LOWORD(wParam),
MF_BYCOMMAND);
return 0;
break;
case IDC_EDIT_QUICK_FIND:
switch(HIWORD(wParam)) //check the notification code
{
case EN_CHANGE: //edit box changed
DoLVQuickFind(bwi_hWndEditQF,bwi_hWndListAB);
/* if(bwi_bDoQuickFilter)
{
DoLVQuickFilter(bwi_lpAdrBook,
bwi_hWndEditQF,
bwi_hWndListAB,
&bwi_SortInfo,
AB_FUZZY_FIND_NAME | AB_FUZZY_FIND_EMAIL,
1,
&bwi_lpContentsList);
ShowLVCountinStatusBar(lpbwi);
}
*/
break;
}
break;
case IDM_TOOLS_EXPORT_WAB:
HrExportWAB(hWnd, lpbwi);
break;
case IDM_TOOLS_EXPORT_OTHER:
case IDM_TOOLS_IMPORT_OTHER:
{
// if there is a current user, then we let wabmig.exe automatically
// loginto the current user in the WAB .. else we need to send the filename etc
//
BOOL bImport = (GET_WM_COMMAND_ID(wParam, lParam) == IDM_TOOLS_IMPORT_OTHER);
TCHAR szParam[MAX_PATH * 2];
if(bIsThereACurrentUser(bwi_lpIAB))
{
StrCpyN(szParam, bImport ? szIMPORT : szEXPORT, ARRAYSIZE(szParam));
}
else
{
LPTSTR lpWABFile = NULL, lpProfileID = szEmpty;
lpWABFile = GetWABFileName( bwi_lpIAB->lpPropertyStore->hPropertyStore, FALSE);
if(!lpWABFile || !lstrlen(lpWABFile))
lpWABFile = szEmpty;
wnsprintf(szParam, ARRAYSIZE(szParam), (bImport ? szIMPORTwProfileParam : szEXPORTwProfileParam),
szEmpty, lpWABFile);
}
RunWABApp(hWnd, szWABMigRegPathKey, szWABMIG, szParam);
}
break;
case IDM_TOOLS_IMPORT_WAB:
bwi_bDontRefreshLV = TRUE;
//bwi_bDeferNotification = TRUE;
HrImportWABFile(hWnd, bwi_lpAdrBook, MAPI_DIALOG, NULL);
bwi_bDontRefreshLV = FALSE;
RefreshListView(lpbwi, &ftLast);
break;
#ifdef VCARD
case IDM_TOOLS_EXPORT_VCARD:
bwi_bDontRefreshLV = TRUE;
VCardExportSelectedItems(bwi_hWndListAB, bwi_lpAdrBook);
bwi_bDontRefreshLV = FALSE;
return(0);
case IDM_TOOLS_IMPORT_VCARD:
OpenAndAddVCard(lpbwi, NULL);
return(0);
#endif
}
}
break;
case WM_TIMER:
{
// Check if we need to refresh
switch(wParam)
{
/*
case WAB_REFRESH_TIMER:
if ( CheckChangedWAB(bwi_lpIAB->lpPropertyStore, &ftLast))
{
if(!bwi_bDontRefreshLV)
RefreshListView(lpbwi,&ftLast);
return(0);
}
else
{
return(DefWindowProc(hWnd,uMsg,wParam,lParam));
}
break;
*/
case WAB_TOOLTIP_TIMER_ID:
{
if(GetActiveWindow() == hWnd)
{
// We seem to get the message anytime the mouse is sitting idle on the
// list view - or when the selection changes between items
if(bwi_tt_bActive)
{
// The tooltip is already active
// Get the item index number of the item under the mouse
//
int nItem = HitTestLVSelectedItem(lpbwi);
if(nItem != bwi_tt_iItem)
{
bwi_tt_bShowTooltip = FALSE;
bwi_tt_iItem = nItem;
}
else
{
if(!bwi_tt_bShowTooltip)
{
// if this is an item other than the previous item
// we update the tooltip and move it
TOOLINFO ti = {0};
bwi_tt_bShowTooltip = TRUE;
bwi_tt_iItem = nItem;
FillTooltipInfo(lpbwi, &ti);
bwi_tt_szTipText[0]='\0';
ti.lpszText = szEmpty;
// There is a case where nItem transitions from valid to
// invalid (-1) item. Cover that case too.
if(nItem != -1)
UpdateTooltipTextBuffer(lpbwi, nItem);
// Set the tooltip text to TEXT("") - this will hide the tooltip
ToolTip_UpdateTipText(bwi_hWndTT, (LPARAM)&ti);
if(nItem != -1)
{
POINT pt;
// Move the tooltip
GetCursorPos(&pt);
SendMessage(bwi_hWndTT,TTM_TRACKPOSITION,0,(LPARAM)MAKELPARAM(pt.x+15,pt.y+15));
// Set the new text to the tooltip
ti.lpszText = bwi_tt_szTipText;
ToolTip_UpdateTipText(bwi_hWndTT,(LPARAM)&ti);
}
}
}
}
}
else
{
// reset the tooltip text ...
if(bwi_tt_bActive)
{
//set the tooltip text to empty
TOOLINFO ti = {0};
FillTooltipInfo(lpbwi, &ti);
ti.lpszText = szEmpty; //LPSTR_TEXTCALLBACK;
ToolTip_UpdateTipText(bwi_hWndTT, (LPARAM)&ti);
bwi_tt_iItem = -1;
}
}
}
break;
}
}
break;
case WM_GETMINMAXINFO:
//enforce a minimum size for sanity
return EnforceMinSize(lpbwi, hWnd, uMsg, wParam, lParam);
break;
case PUI_OFFICE_COMMAND:
// WAB should not shut down if it is running as part of some other process .. it should only shut down if
// it is running in a seperate process ..
// To find out if we were invoked by wab.exe, check the cached guidPSExt on the LPIAB object
if(memcmp(&bwi_lpIAB->guidPSExt, &MPSWab_GUID_V4, sizeof(GUID)))
{
DebugTrace( TEXT("Ignoring the Plug_UI command...\n"));
return 0;
}
// We get this message when user switches his locale and IE tells us it wants us to shut down
if(wParam == PLUGUI_CMD_QUERY)
{
PLUGUI_QUERY pq;
pq.uQueryVal = 0; // initialize
pq.PlugUIInfo.uMajorVersion = OFFICE_VERSION_9; // Value filled in by Apps
pq.PlugUIInfo.uOleServer = FALSE; // Value filled in by Apps
return (pq.uQueryVal); // The state of the App
}
// for any others parameters, including PLUGUI_CMD_SHUTDOWN
// fall to close application
case WM_CLOSE:
{
BOOL bDragDrop = FALSE;
if(bwi_lpIWABDragDrop)
{
bDragDrop = TRUE;
RevokeDragDrop(bwi_hWndListAB);
RevokeDragDrop(bwi_hWndTV);
CoLockObjectExternal((LPUNKNOWN) bwi_lpIWABDragDrop, FALSE, TRUE);
bwi_lpIWABDragDrop->lpVtbl->Release(bwi_lpIWABDragDrop);
bwi_lpIWABDragDrop = NULL;
}
bwi_bDontRefreshLV = TRUE;
ClearTreeViewItems(bwi_hWndTV);
ListView_DeleteAllItems(bwi_hWndListAB);
//
// Save the sort info to the registry
//
WriteRegistrySortInfo(bwi_lpIAB, bwi_SortInfo);
SaveCurrentPosition(lpbwi, hWnd,bwi_hWndListAB,bwi_hWndBB,bwi_hWndSB);
if(bwi_lpfnDismiss)
{
(*bwi_lpfnDismiss)((ULONG_PTR) hWnd, (LPVOID) bwi_lpvDismissContext);
bwi_lpfnDismiss = NULL;
}
bwi_lpvDismissContext = NULL;
DestroyWindow(hWnd);
// In case the search window was every shown and the LDAP Client DLL was
// initialized, we deinitialize it just once to save time, when this
// window shuts down ...
{
HCURSOR hOldCur = SetCursor(LoadCursor(NULL, IDC_WAIT));
DeinitLDAPClientLib();
SetCursor(hOldCur);
}
OleFlushClipboard();
return 0;
}
break;
case WM_DESTROY:
{
int i = 0;
LPPTGDATA lpPTGData=GetThreadStoragePointer();
bwi_lpIAB->hWndBrowse = NULL;
if(bwi_lpAdviseSink)
{
bwi_lpAdrBook->lpVtbl->Unadvise(bwi_lpAdrBook, bwi_ulAdviseConnection);
bwi_lpAdviseSink->lpVtbl->Release(bwi_lpAdviseSink);
bwi_lpAdviseSink = NULL;
bwi_ulAdviseConnection = 0;
}
if (bwi_lpAdrBook)
{
ReleasePropertyStore(bwi_lpIAB->lpPropertyStore);
bwi_lpAdrBook->lpVtbl->Release(bwi_lpAdrBook);
bwi_lpAdrBook = NULL;
bwi_lpIAB = NULL;
pt_lpIAB = NULL;
}
if (bwi_tt_TooltipTimer)
KillTimer(hWnd, bwi_tt_TooltipTimer);
if (uTimer)
KillTimer(hWnd, uTimer);
if(bwi_hWndAB)
DestroyMenu(GetMenu(bwi_hWndAB));
// reset subclassed procs
for(i=0;i<s_Max;i++)
{
SetWindowLongPtr (bwi_s_hWnd[i], GWLP_WNDPROC, (LONG_PTR) bwi_fnOldProc[i]);
}
DestroyImageLists(lpbwi);
CleanUpGlobals(lpbwi);
LocalFree(lpbwi);
lpbwi = NULL;
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LPARAM) NULL);
// Delete background brush, WIN16 specific.
IF_WIN16(DeleteObject(hBrushBack);)
}
break;
case WM_CREATE:
{
lpbwi = (LPBWI) ((LPCREATESTRUCT) lParam)->lpCreateParams;
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LPARAM) lpbwi);
bwi_hWndAB = hWnd;
bwi_lpIAB->hWndBrowse = hWnd;
CreateAddressBookChildren(lpbwi, hWnd);
InitChildren(lpbwi, hWnd);
ReadRegistrySortInfo(bwi_lpIAB,&bwi_SortInfo);
SetPreviousSessionPosition(lpbwi, hWnd, bwi_hWndListAB, bwi_hWndBB,bwi_hWndSB);
SetColumnHeaderBmp(bwi_hWndListAB, bwi_SortInfo);
// Tooltip Timer
bwi_tt_TooltipTimer = SetTimer(hWnd,
WAB_TOOLTIP_TIMER_ID,
WAB_TOOLTIP_TIMER_TIMEOUT,
NULL);
if(bwi_lpAdviseSink)
{
// Register for notifications
bwi_lpAdrBook->lpVtbl->Advise( bwi_lpAdrBook, 0, NULL, fnevObjectModified,
bwi_lpAdviseSink, &bwi_ulAdviseConnection);
}
/*
// UI Refresh timer
uTimer = SetTimer(hWnd, // handle of window for timer messages
WAB_REFRESH_TIMER, // timer identifier
WAB_REFRESH_TIMEOUT, // time-out value
NULL); // address of timer procedure
*/
// Create default background brush, WIN16 only
IF_WIN16(hBrushBack = CreateSolidBrush (GetSysColor (COLOR_BTNFACE)) ;)
HrCreateIWABDragDrop(&bwi_lpIWABDragDrop);
if(bwi_lpIWABDragDrop)
{
bwi_lpIWABDragDrop->m_lpv = (LPVOID) lpbwi;
UIOLEInit();
CoLockObjectExternal((LPUNKNOWN) bwi_lpIWABDragDrop, TRUE, FALSE);
RegisterDragDrop(bwi_hWndListAB, (LPDROPTARGET) bwi_lpIWABDragDrop->lpIWABDropTarget);
RegisterDragDrop(bwi_hWndTV, (LPDROPTARGET) bwi_lpIWABDragDrop->lpIWABDropTarget);
}
{
LPPTGDATA lpPTGData=GetThreadStoragePointer();
if(pt_bFirstRun)
pt_bFirstRun = FALSE;
}
}
if(bIsThereACurrentUser(bwi_lpIAB))
UpdateTVGroupSelection(bwi_hWndTV, &(bwi_lpIAB->lpWABCurrentUserFolder->sbEID));
break;
case WM_SIZE:
ResizeAddressBookChildren(lpbwi, hWnd);
break;
case WM_KEYDOWN:
{
switch(wParam)
{
case VK_TAB:
SetFocus(bwi_s_hWnd[bwi_iFocus]);
return 0;
break;
case VK_ESCAPE:
SendMessage(hWnd,WM_CLOSE,0,0L);
return 0;
break;
}
}
break;
case WM_NOTIFY:
switch((int) wParam)
{
case IDC_LISTVIEW:
return ProcessListViewMessages(lpbwi, hWnd,uMsg,wParam,lParam);
break;
case IDC_TREEVIEW:
return ProcessTreeViewMessages(lpbwi, hWnd,uMsg,wParam,lParam, &ftLast);
break;
}
switch(((LPNMHDR) lParam)->code)
{
case TTN_POP:
{
// Need to turn off the hot item
// Find the first selected item in the list view
//int nItem = ListView_GetNextItem(bwi_hWndListAB, -1, LVNI_SELECTED);
ListView_SetHotItem(bwi_hWndListAB, -1); //nItem);
}
break;
case TTN_SHOW:
{
// Set the hot item
ListView_SetHotItem(bwi_hWndListAB, bwi_tt_iItem);
}
break;
case TTN_NEEDTEXT:
{
LPTOOLTIPTEXT lpttt;
int nItem = HitTestLVSelectedItem(lpbwi);
DebugPrintTrace(( TEXT("Tooltip NeedText\n")));
lpttt = (LPTOOLTIPTEXT) lParam;
if (nItem != -1)
{
UpdateTooltipTextBuffer(lpbwi, nItem);
lpttt->lpszText = bwi_tt_szTipText;
}
else
lpttt->lpszText = szEmpty;
}
break;
}
break;
case WM_SETTINGCHANGE:
// [PaulHi] 3/17/99 Raid 68541 Redraw window with new system settings
// [PaulHi] 4/19/99 Recompute the font sizes, in case they changed.
// Fonts used for bolding list items
DeleteFonts();
InitFonts();
// Fonts used for all children windows
if(pt_hDefFont)
{
DeleteObject(pt_hDefFont);
pt_hDefFont = NULL;
}
if(pt_hDlgFont)
{
DeleteObject(pt_hDlgFont);
pt_hDlgFont = NULL;
}
EnumChildWindows(hWnd,
SetChildDefaultGUIFont,
(LPARAM) PARENT_IS_WINDOW);
InvalidateRect(hWnd, NULL, TRUE);
ResizeAddressBookChildren(lpbwi, hWnd);
// Drop through...
case WM_SYSCOLORCHANGE:
{
//Forward any system changes to the list view
SendMessage(bwi_hWndListAB, uMsg, wParam, lParam);
SetColumnHeaderBmp(bwi_hWndListAB, bwi_SortInfo);
SendMessage(bwi_hWndBB, uMsg, wParam, lParam);
}
break;
#ifndef WIN16 // Disable CONTEXTMENU here.
// All context menu will be handled notify handler.
case WM_CONTEXTMENU:
{
if ((HWND)wParam == bwi_hWndListAB)
{
#ifdef COLSEL_MENU
HWND hHeader = ListView_GetHeader(bwi_hWndListAB);
POINT pointScreen, pointHeader;
DWORD dwPos;
char szClass[50];
dwPos = GetMessagePos();
pointScreen.x = LOWORD(dwPos);
pointScreen.y = HIWORD(dwPos);
if ( hHeader )
{
HD_HITTESTINFO hdhti;
pointHeader = pointScreen;
ScreenToClient( hHeader, &pointHeader) ;
hdhti.pt = pointHeader;
SendMessage( hHeader, HDM_HITTEST, (WPARAM)(0),
(LPARAM)(HD_HITTESTINFO FAR *)&hdhti);
if( hdhti.flags == HHT_ONHEADER &&
(hdhti.iItem == colHomePhone || hdhti.iItem == colOfficePhone) )
{
lpbwi->iSelColumn = hdhti.iItem;
ShowLVContextMenu( lvMainABHeader, bwi_hWndListAB,
NULL, lParam, (LPVOID)IntToPtr(hdhti.iItem), bwi_lpAdrBook, bwi_hWndTV);
}
else
{
#endif // COLSEL_MENU
ShowLVContextMenu( lvMainABView,
bwi_hWndListAB,
NULL, lParam,
NULL, bwi_lpAdrBook, bwi_hWndTV);
#ifdef COLSEL_MENU
}
}
#endif // COLSEL_MENU
}
else if((HWND)wParam==bwi_hWndTV)
{
HTREEITEM hti = NULL;
if(lParam == -1)
hti = TreeView_GetSelection(bwi_hWndTV);
else
{
TV_HITTESTINFO tvhti;
POINT pt = {LOWORD(lParam), HIWORD(lParam)};
ScreenToClient(bwi_hWndTV, &pt);
tvhti.pt = pt;
hti = TreeView_HitTest(bwi_hWndTV, &tvhti);
}
if (hti == NULL)
return 0;
TreeView_SelectDropTarget(bwi_hWndTV, hti);
// cache the selected item for later processing
bwi_hti = hti;
bwi_lpUserFolder = GetSelectedUserFolder(lpbwi);
if(!ShowLVContextMenu( lvMainABTV,
bwi_hWndListAB,
NULL, lParam,
(LPVOID) bwi_lpUserFolder, bwi_lpAdrBook, bwi_hWndTV))
{
bwi_hti = NULL;
}
TreeView_SelectDropTarget(bwi_hWndTV, NULL);
}
else
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
break;
#endif // !WIN16
#ifdef WIN16 // Change Static controls background color
case WM_CTLCOLOR:
switch(HIWORD(lParam)) {
case CTLCOLOR_STATIC:
/* Set background to btnface color */
SetBkColor((HDC) wParam,GetSysColor (COLOR_BTNFACE) );
return (DWORD)hBrushBack;
}
return NULL;
#endif
default:
#ifndef WIN16 // WIN16 doesn't support MSWheel.
if((g_msgMSWheel && uMsg == g_msgMSWheel)
// || uMsg == WM_MOUSEWHEEL
)
{
if(bIsFocusOnTV(lpbwi))
SendMessage(bwi_hWndTV, uMsg, wParam, lParam);
else
SendMessage(bwi_hWndListAB, uMsg, wParam, lParam);
break;
}
#endif // !WIN16
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
return 0;
}
//$$
//*------------------------------------------------------------------------
//| CreateAddressBookChildren:
//|
//*------------------------------------------------------------------------
void CreateAddressBookChildren(LPBWI lpbwi, HWND hWndParent)
{
HINSTANCE hinst = hinstMapiXWAB;
TCHAR szBuf[MAX_PATH];
HDC hdc = GetDC(hWndParent);
int i;
HFONT hFnt = GetStockObject(DEFAULT_GUI_FONT);
SIZE size;
#ifdef WIN16
// Remove bold.
LOGFONT lf;
GetObject(hFnt, sizeof(LOGFONT), &lf);
lf.lfWeight = FW_NORMAL;
DeleteObject(hFnt);
LoadString(hinstMapiX, idsDefaultDialogFace, lf.lfFaceName, CharSizeOf(lf.lfFaceName));
hFnt = CreateFontIndirect(&lf);
#endif
bwi_hWndBB = CreateCoolBar(lpbwi, hWndParent);
bwi_hWndSB = CreateWindowEx( 0,
STATUSCLASSNAME,
szEmpty,
WS_CHILD /*| WS_BORDER */| WS_VISIBLE | SBS_SIZEGRIP,
0,0,0,0,
hWndParent,
(HMENU) IDC_STATUSBAR,
hinst,
NULL);
SendMessage(bwi_hWndSB, WM_SETFONT, (WPARAM) hFnt, (LPARAM) TRUE);
bwi_hWndTV = CreateWindowEx( WS_EX_CLIENTEDGE,
WC_TREEVIEW,
(LPTSTR) NULL,
WS_VISIBLE | WS_CHILD | TVS_HASLINES | TVS_LINESATROOT |
TVS_HASBUTTONS | TVS_SHOWSELALWAYS | WS_BORDER,
0,0,
150, //default width
CW_USEDEFAULT,
hWndParent,
(HMENU) IDC_TREEVIEW,
hinst,
NULL);
SendMessage(bwi_hWndTV, WM_SETFONT, (WPARAM) hFnt, (LPARAM) TRUE);
{
#ifndef WIN16
WNDCLASSEX wc = {0};
#else
WNDCLASS wc = {0};
#endif
bwi_hWndSplitter = CreateWindowEx(0,
TEXT("STATIC"),
szEmpty,
WS_CHILD | WS_VISIBLE,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
hWndParent,
(HMENU) IDC_SPLITTER,
hinst,
NULL);
SendMessage(bwi_hWndSplitter, WM_SETFONT, (WPARAM) hFnt, (LPARAM) TRUE);
}
bwi_hWndTT = CreateWindowEx( 0,
TOOLTIPS_CLASS,
(LPTSTR) NULL,
TTS_ALWAYSTIP,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
hWndParent,
(HMENU) NULL, //IDC_TOOLTIP,
hinst,
NULL);
SendMessage(bwi_hWndTT, WM_SETFONT, (WPARAM) hFnt, (LPARAM) TRUE);
// Create main list view
bwi_hWndListAB = CreateWindowEx (
WS_EX_CLIENTEDGE,
WC_LISTVIEW, // list view class
szEmpty, // no default text
WS_TABSTOP | WS_HSCROLL | WS_VSCROLL |
WS_VISIBLE | WS_CHILD | //WS_BORDER |
LVS_REPORT | LVS_SHOWSELALWAYS |
//LVS_AUTOARRANGE |
WS_EX_CLIENTEDGE, // styles
0, 0, 0, 0,
hWndParent,
(HMENU) IDC_LISTVIEW,
hinst,
NULL);
//ListView_SetExtendedListViewStyle(bwi_hWndListAB, LVS_EX_HEADERDRAGDROP);
// create caption for quick find edit box
ZeroMemory(&size, sizeof(size));
LoadString(hinstMapiX, idsQuickFindCaption, szBuf, CharSizeOf(szBuf));
GetTextExtentPoint32(hdc, szBuf, lstrlen(szBuf), &size);
bwi_hWndStaticQF = CreateWindow( TEXT("STATIC"),
szBuf,
WS_TABSTOP | WS_CHILD | WS_VISIBLE,
0,0,size.cx,size.cy,
hWndParent,
(HMENU) IDC_STATIC_QUICK_FIND,
hinst,
NULL);
#if 0 // Disable temporarily untile comctlie.dll export this.
#ifdef WIN16
Ctl3dSubclassCtl(bwi_hWndStaticQF);
#endif
#endif
SendMessage(bwi_hWndStaticQF, WM_SETFONT, (WPARAM) hFnt, (LPARAM) TRUE);
UpdateWindow(bwi_hWndStaticQF);
// create quick find edit box
bwi_hWndEditQF = CreateWindowEx( WS_EX_CLIENTEDGE,
TEXT("EDIT"),
NULL,
WS_TABSTOP | WS_CHILD | WS_VISIBLE |
ES_AUTOHSCROLL | ES_LEFT | ES_AUTOVSCROLL ,
0,0,
size.cx,size.cy+4,
hWndParent,
(HMENU) IDC_EDIT_QUICK_FIND,
hinst,
NULL);
#if 0 // Disable temporarily untile comctlie.dll export this.
#ifdef WIN16
Ctl3dSubclassCtl(bwi_hWndEditQF);
#endif
#endif
SendMessage(bwi_hWndEditQF, WM_SETFONT, (WPARAM) hFnt, (LPARAM) TRUE);
SendMessage(bwi_hWndEditQF, EM_SETLIMITTEXT,(WPARAM) MAX_DISPLAY_NAME_LENGTH-1,0);
if (hdc) ReleaseDC(hWndParent,hdc);
// Sub class some of the controls
bwi_s_hWnd[s_EditQF] = bwi_hWndEditQF;
bwi_s_hWnd[s_ListAB] = bwi_hWndListAB;
bwi_s_hWnd[s_TV] = bwi_hWndTV;
for(i=0;i<s_Max;i++)
{
bwi_fnOldProc[i] = (WNDPROC) SetWindowLongPtr (bwi_s_hWnd[i], GWLP_WNDPROC, (LONG_PTR) SubClassedProc);
}
SetFocus(bwi_hWndEditQF);
return;
}
//$$/////////////////////////////////////////////////////////////
//
// ResizeAddressBookChildren(HWND hWndParent)
//
// Resizing and moving around
//
///////////////////////////////////////////////////////////////
void ResizeAddressBookChildren(LPBWI lpbwi, HWND hWndParent)
{
RECT rc, rc1;
int BBx,BBy,BBw,BBh;
int SBx,SBy,SBw,SBh;
int QFx,QFy,QFw,QFh;
int EDx,EDy,EDw,EDh;
int LVx,LVy,LVw,LVh;
TCHAR szBuf[MAX_PATH];
HDC hdc;
SIZE size;
RECT rcTV;
int TVx=0, TVy=0, TVw=0, TVh=0;
int TCKx = 0, TCKy=0, TCKw=0, TCKh=0;
// calculate button, static, and edit sizes from the font.
hdc = GetDC(hWndParent);
GetClientRect(hWndParent,&rc);
GetChildClientRect(bwi_hWndBB,&rc1);
// Button Bars coordinates
BBx = BBy = 0; BBw = rc.right; BBh = rc1.bottom - rc1.top;
if (IsWindowVisible(bwi_hWndBB))
MoveWindow(bwi_hWndBB, BBx, BBy,BBw, BBh,TRUE);
else
BBw = BBh = 0;
if (IsWindowVisible(bwi_hWndTV))
{
GetChildClientRect(bwi_hWndTV, &rcTV);
TVx = 0;
TVw = rcTV.right - rcTV.left;
TCKx = TVw;
TCKw = BORDER;
}
// Quick Find labels coordinates
GetTextExtentPoint32(hdc, szBuf, GetWindowText(bwi_hWndStaticQF, szBuf, CharSizeOf(szBuf)), &size);
QFx = TVx + TVw + BORDER;
QFy = BBy+BBh+BORDER;
QFw = size.cx;
QFh = size.cy;
//Edit Box coordinates
EDx = QFx+QFw+CONTROL_SPACING;
EDy = QFy;
QFy += 2;
GetChildClientRect(bwi_hWndEditQF,&rc1);
EDh = rc1.bottom - rc1.top;
EDw = QFw;
//List View Dimensions
LVx = TVx + TVw + BORDER;
LVy = EDy+EDh+BORDER;
LVw = rc.right - rc.left;// - 2*BORDER;
LVh = rc.bottom - LVy;// - BORDER;
// [PaulHi] 3/17/99 Raid 68541
// We can't just set the status bar height to 14 because in large mode Windows will
// draw outside the status bar window (very ugly). We want the status bar to be
// smaller than system default so we (safely) subtract six pixels from the height.
SBx = 0;
SBh = GetSystemMetrics(SM_CYCAPTION) - 4;
SBh = (SBh > 0) ? SBh : 14;
SBy = rc.bottom - SBh;
SBw = rc.right - rc.left;
if(IsWindowVisible(bwi_hWndSB))
LVh = LVh - SBh - 2*BORDER;
TVy = QFy;
TVh = rc.bottom - TVy;
if(IsWindowVisible(bwi_hWndSB))
TVh = TVh - SBh - 2*BORDER;
LVw = LVw - BORDER - TVw;
if (IsWindowVisible(bwi_hWndTV))
{
TCKy = TVy;
TCKh = TVh;
}
{
HDWP hdwp = BeginDeferWindowPos(6);
MoveWindow(bwi_hWndEditQF, EDx, EDy, EDw, EDh, TRUE);
MoveWindow(bwi_hWndStaticQF, QFx, QFy, QFw, QFh, TRUE);
MoveWindow(bwi_hWndListAB, LVx, LVy, LVw, LVh, TRUE);
MoveWindow(bwi_hWndSB, SBx, SBy, SBw, SBh, TRUE);
if (IsWindowVisible(bwi_hWndTV))
{
MoveWindow(bwi_hWndTV, TVx, TVy, TVw, TVh, TRUE);
MoveWindow(bwi_hWndSplitter, TCKx, TCKy, TCKw, TCKh, TRUE);
}
EndDeferWindowPos(hdwp);
}
ReleaseDC(hWndParent, hdc);
return;
}
//$$/////////////////////////////////////////////////////////////
//
// Initialize the kid windows
//
///////////////////////////////////////////////////////////////
void InitChildren(LPBWI lpbwi, HWND hWndParent)
{
HrInitListView(bwi_hWndListAB, LVS_REPORT, TRUE);
InitMultiLineToolTip(lpbwi, hWndParent);
{
HIMAGELIST hSmall = gpfnImageList_LoadImage( hinstMapiX,
MAKEINTRESOURCE(IDB_BITMAP_SMALL),
//(LPCTSTR) ((DWORD) ((WORD) (IDB_BITMAP_SMALL))),
S_BITMAP_WIDTH,
0,
RGB_TRANSPARENT,
IMAGE_BITMAP,
0);
// Associate the image lists with the list view control.
TreeView_SetImageList (bwi_hWndTV, hSmall, TVSIL_NORMAL);
//FillTreeView(bwi_hWndTV, NULL);
}
// Set the font of all the children to the default GUI font
EnumChildWindows( hWndParent,
SetChildDefaultGUIFont,
(LPARAM) PARENT_IS_WINDOW);
SendMessage(hWndParent,WM_COMMAND,IDM_VIEW_DETAILS,0);
bwi_bDoQuickFilter = TRUE;
SetFocus(bwi_hWndEditQF);
}
//$$/////////////////////////////////////////////////////////////
//
// Change list views styles and possibly menus also
//
///////////////////////////////////////////////////////////////
void SetListViewStyle(LPBWI lpbwi, int MenuID)
{
DWORD dwStyle = GetWindowLong(bwi_hWndListAB,GWL_STYLE);
BOOL bUseCurrentSortSettings = FALSE;
// Right now we just change the style here
// later on we can update the menu etc. to reflect the style and
switch(MenuID)
{
case IDM_VIEW_DETAILS:
if((dwStyle & LVS_TYPEMASK) != LVS_REPORT)
SetWindowLong(bwi_hWndListAB,GWL_STYLE,(dwStyle & ~LVS_TYPEMASK) | LVS_REPORT);
break;
case IDM_VIEW_SMALLICON:
if((dwStyle & LVS_TYPEMASK) != LVS_SMALLICON)
SetWindowLong(bwi_hWndListAB,GWL_STYLE,(dwStyle & ~LVS_TYPEMASK) | LVS_SMALLICON);
break;
case IDM_VIEW_LARGEICON:
if((dwStyle & LVS_TYPEMASK) != LVS_ICON)
SetWindowLong(bwi_hWndListAB,GWL_STYLE,(dwStyle & ~LVS_TYPEMASK) | LVS_ICON);
break;
case IDM_VIEW_LIST:
if((dwStyle & LVS_TYPEMASK) != LVS_LIST)
SetWindowLong(bwi_hWndListAB,GWL_STYLE,(dwStyle & ~LVS_TYPEMASK) | LVS_LIST);
break;
}
{
//
// If we are not in details view, we dont really want to be able to sort
// by phone number and email address .. hence we disable those menu
// options under certain conditions ...
//
HMENU hMenuMain = GetMenu(bwi_hWndAB);
HMENU hMenuView = GetSubMenu(hMenuMain,idmView);
int nDiff = idmViewMax - GetMenuItemCount(hMenuView); // in case stuff was deleted off this menu
HMENU hMenu = GetSubMenu(hMenuView, idmSortBy - nDiff);
if (MenuID == IDM_VIEW_DETAILS)
{
EnableMenuItem(hMenu,IDM_VIEW_SORTBY_EMAILADDRESS,MF_BYCOMMAND | MF_ENABLED);
EnableMenuItem(hMenu,IDM_VIEW_SORTBY_BUSINESSPHONE,MF_BYCOMMAND | MF_ENABLED);
EnableMenuItem(hMenu,IDM_VIEW_SORTBY_HOMEPHONE,MF_BYCOMMAND | MF_ENABLED);
}
else
{
EnableMenuItem(hMenu,IDM_VIEW_SORTBY_EMAILADDRESS,MF_BYCOMMAND | MF_GRAYED);
EnableMenuItem(hMenu,IDM_VIEW_SORTBY_BUSINESSPHONE,MF_BYCOMMAND | MF_GRAYED);
EnableMenuItem(hMenu,IDM_VIEW_SORTBY_HOMEPHONE,MF_BYCOMMAND | MF_GRAYED);
}
}
if (MenuID != IDM_VIEW_DETAILS)
{
SORT_INFO SortTmp = bwi_SortInfo;
//hack
SendMessage(bwi_hWndListAB, WM_SETREDRAW, (WPARAM) FALSE, 0);
bUseCurrentSortSettings = FALSE;
SortListViewColumn(bwi_lpIAB, bwi_hWndListAB, colDisplayName, &bwi_SortInfo, bUseCurrentSortSettings);
bwi_SortInfo = SortTmp;
bwi_SortInfo.iOldSortCol = colDisplayName;
bUseCurrentSortSettings = TRUE;
SortListViewColumn(bwi_lpIAB, bwi_hWndListAB, colDisplayName, &bwi_SortInfo, bUseCurrentSortSettings);
SendMessage(bwi_hWndListAB, WM_SETREDRAW, (WPARAM) TRUE, 0);
}
UpdateSortMenus(lpbwi, bwi_hWndAB);
return;
}
//$$/////////////////////////////////////////////////////////////
//
// Resets the globals in case someone drops by again
//
///////////////////////////////////////////////////////////////
void CleanUpGlobals(LPBWI lpbwi)
{
if (bwi_lpContentsList)
FreeRecipList(&bwi_lpContentsList);
bwi_hWndListAB = NULL;
bwi_hWndBB = NULL;
bwi_hWndSB = NULL;
bwi_hWndEditQF =NULL;
bwi_hWndStaticQF = NULL;
bwi_hWndAB = NULL;
bwi_hWndTT = NULL;
bwi_tt_bActive = FALSE;
bwi_tt_iItem = -1;
bwi_tt_szTipText[0]='\0';
bwi_tt_TooltipTimer = 0;
bwi_hWndTV = NULL;
bwi_hWndSplitter = NULL;
bwi_bDontRefreshLV = FALSE;
ReadRegistrySortInfo(bwi_lpIAB, &bwi_SortInfo);
return;
}
/*
- bCheckIfOnlyGroupsSelected
-
- Returns TRUE if all the selected items in the ListView are only Groups (no Contacts)
*
*/
BOOL bCheckIfOnlyGroupsSelected(HWND hWndLV)
{
int nSelected = ListView_GetSelectedCount(hWndLV);
int iItemIndex = -1;
if(nSelected <= 0)
return FALSE;
while((iItemIndex = ListView_GetNextItem(hWndLV, iItemIndex, LVNI_SELECTED))!= -1)
{
// Get the entryid of the selected item
LPRECIPIENT_INFO lpItem = GetItemFromLV(hWndLV, iItemIndex);
if(lpItem && lpItem->ulObjectType == MAPI_MAILUSER)
return FALSE;
}
return TRUE;
}
//$$////////////////////////////////////////////////////////////////////////////////////////
//
// Processes messages for the list view control
//
//////////////////////////////////////////////////////////////////////////////////////////
LRESULT ProcessListViewMessages(LPBWI lpbwi, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
NM_LISTVIEW * pNm = (NM_LISTVIEW *)lParam;
HWND hWndAddr = pNm->hdr.hwndFrom;
switch(pNm->hdr.code)
{
case LVN_COLUMNCLICK:
SortListViewColumn(bwi_lpIAB, hWndAddr, pNm->iSubItem, &bwi_SortInfo, FALSE);
UpdateSortMenus(lpbwi, bwi_hWndAB);
break;
case LVN_KEYDOWN:
UpdateToolbarAndMenu(lpbwi);
switch(((LV_KEYDOWN FAR *) lParam)->wVKey)
{
case VK_DELETE:
SendMessage (hWnd, WM_COMMAND, (WPARAM) IDM_FILE_DELETE, 0);
return 0;
break;
case VK_RETURN:
SendMessage (hWnd, WM_COMMAND, (WPARAM) IDM_FILE_PROPERTIES, 0);
return 0;
}
break;
//case LVN_ITEMCHANGED:
case NM_CLICK:
case NM_RCLICK:
{
UpdateToolbarAndMenu(lpbwi);
#ifdef WIN16 // Context menu handler for WIN16
if( pNm->hdr.code == NM_RCLICK && pNm->hdr.hwndFrom == bwi_hWndListAB)
{
POINT pt;
GetCursorPos(&pt);
ShowLVContextMenu( lvMainABView,
bwi_hWndListAB,
NULL, //bwi_hWndCombo,
MAKELPARAM(pt.x, pt.y),
NULL,
bwi_lpAdrBook, bwi_hWndTV);
}
#endif // WIN16
}
break;
case NM_SETFOCUS:
UpdateToolbarAndMenu(lpbwi);
break;
case NM_DBLCLK:
SendMessage (hWnd, WM_COMMAND, (WPARAM) IDM_FILE_PROPERTIES, 0);
return 0;
break;
case NM_CUSTOMDRAW:
return ProcessLVCustomDraw(NULL, lParam, FALSE);
break;
case LVN_BEGINDRAG:
case LVN_BEGINRDRAG:
{
DWORD dwEffect = 0;
LPIWABDATAOBJECT lpIWABDataObject = NULL;
bwi_bDontRefreshLV = TRUE; // prevent refreshes as this action is based on the selection
HrCreateIWABDataObject((LPVOID) lpbwi, bwi_lpAdrBook, bwi_hWndListAB, &lpIWABDataObject,
FALSE,bCheckIfOnlyGroupsSelected(bwi_hWndListAB));
if(lpIWABDataObject)
{
bwi_lpIWABDragDrop->m_bSource = TRUE;
DoDragDrop( (LPDATAOBJECT) lpIWABDataObject,
(LPDROPSOURCE) bwi_lpIWABDragDrop->lpIWABDropSource,
DROPEFFECT_COPY | DROPEFFECT_MOVE,
&dwEffect);
bwi_lpIWABDragDrop->m_bSource = FALSE;
lpIWABDataObject->lpVtbl->Release(lpIWABDataObject);
}
RefreshListView(lpbwi, NULL);
bwi_bDontRefreshLV = FALSE; // prevent refreshes as this action is based on the selection
}
return 0;
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
//$$/////////////////////////////////////////////////////////////////////////
//
//
//
///////////////////////////////////////////////////////////////////////////
LRESULT EnforceMinSize(LPBWI lpbwi, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LPPOINT lppt = (LPPOINT)lParam; // lParam points to array of POINTs
RECT rc1, rc2;
if(lpbwi)
{
if(bwi_hWndEditQF)
{
GetWindowRect(bwi_hWndEditQF,&rc1);
GetWindowRect(bwi_hWndStaticQF,&rc2);
lppt[3].x = rc1.right-rc1.left + rc2.right-rc2.left + 2*BORDER; // Set minimum width
lppt[3].y = MIN_WINDOW_H; // Set minimum height
}
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
//$$
//*------------------------------------------------------------------------
//| RefreshListView
//|
//| lpftLast - WAB file time at last update
//*------------------------------------------------------------------------
void RefreshListView(LPBWI lpbwi, LPFILETIME lpftLast)
{
ULONG ulObjectType = 0;
LPSBinary lpsbEID = NULL;
bwi_hti = NULL;
GetCurrentSelectionEID(lpbwi, bwi_hWndTV, &lpsbEID, &ulObjectType, FALSE);
//if(lpsbEID) //root item can have a null entryid - so we default to that item if NULL or err
{
// Refresh the groups list
FillTreeView(lpbwi, bwi_hWndTV, lpsbEID);
LocalFreeSBinary(lpsbEID);
}
// Update the wab file write time so the timer doesn't
// catch this change and refresh.
//if (lpftLast) {
// CheckChangedWAB(bwi_lpIAB->lpPropertyStore, lpftLast);
//}
UpdateSortMenus(lpbwi, bwi_hWndAB);
UpdateToolbarAndMenu(lpbwi);
//DoLVQuickFind(bwi_hWndEditQF,bwi_hWndListAB);
bwi_bDoQuickFilter = FALSE;
SetWindowText(bwi_hWndEditQF,szEmpty);
bwi_bDoQuickFilter = TRUE;
SendMessage(bwi_hWndListAB, WM_SETREDRAW, TRUE, 0L);
return;
}
//$$
//*------------------------------------------------------------------------
//| SubClassedProc - to subclass child controls
//|
//*------------------------------------------------------------------------
LRESULT CALLBACK SubClassedProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
LPBWI lpbwi = (LPBWI) GetWindowLongPtr(GetParent(hWnd), GWLP_USERDATA);
IF_WIN32(int i = GetWindowLong(hWnd, GWL_ID);)
IF_WIN16(int i = GetWindowWord(hWnd, GWW_ID);)
switch(i)
{
case IDC_EDIT_QUICK_FIND:
i = s_EditQF;
break;
case IDC_LISTVIEW:
i = s_ListAB;
break;
case IDC_TREEVIEW:
i = s_TV;
break;
}
switch (iMsg)
{
case WM_KEYDOWN:
switch(wParam)
{
case VK_TAB:
{
int max = s_Max;
if(!IsWindowVisible(bwi_hWndTV)) max--;
SetFocus(bwi_s_hWnd[(i + ((GetKeyState(VK_SHIFT) < 0) ? (max-1) : 1)) % (max)]);
}
break;
case VK_ESCAPE:
SendMessage(bwi_hWndAB,WM_CLOSE,0,0L);
return 0;
break;
case VK_RETURN:
if (i==s_EditQF)
SetFocus(bwi_s_hWnd[(i + ((GetKeyState(VK_SHIFT) < 0) ? (s_Max-1) : 1)) % (s_Max)]);
break;
}
break;
case WM_CHAR:
if (i==s_EditQF || i==s_TV)
{
if ((wParam==VK_RETURN) || (wParam==VK_TAB))
return 0; //prevents irritating beeps
}
break;
case WM_SETFOCUS:
bwi_iFocus = i;
break;
case WM_LBUTTONDBLCLK:
if(i==s_TV)
{
SendMessage(bwi_hWndAB, WM_COMMAND, (WPARAM) IDM_FILE_PROPERTIES, 0);
return FALSE;
}
break;
}
return CallWindowProc(bwi_fnOldProc[i],hWnd,iMsg,wParam,lParam);
}
//$$
//*------------------------------------------------------------------------
//| FindABWindowProc:
//|
//*------------------------------------------------------------------------
STDAPI_(BOOL) FindABWindowProc( HWND hWndToLookAt, LPARAM lParam)
{
HWND * lphWndTmp = (HWND *) lParam;
TCHAR szBuf[MAX_PATH];
// yuk - need a better way to do this - TBD
if (*lphWndTmp == NULL)
{
GetClassName(hWndToLookAt, szBuf, CharSizeOf(szBuf));
if(!lstrcmpi(g_szClass,szBuf))
{
// Found our man
*lphWndTmp = hWndToLookAt;
return FALSE;
}
}
return TRUE;
}
//$$
//*------------------------------------------------------------------------
//| CallBack used by client to send accelerators to us
//|
//*------------------------------------------------------------------------
BOOL STDMETHODCALLTYPE fnAccelerateMessages(ULONG_PTR ulUIParam, LPVOID lpvmsg)
{
LPPTGDATA lpPTGData=GetThreadStoragePointer();
BOOL bRet = FALSE;
if(lpvmsg && pt_hAccTable /*&& IsDialogMessage((HWND) ulUIParam,lpvmsg)*/)
{
bRet = TranslateAcceleratorW((HWND) ulUIParam, // handle of destination window
pt_hAccTable, // handle of accelerator table
(LPMSG) lpvmsg // address of structure with message
);
}
return bRet;
}
//$$
//*------------------------------------------------------------------------
//| Updates the menu item markings whenever we sort ...
//|
//*------------------------------------------------------------------------
void UpdateSortMenus(LPBWI lpbwi, HWND hWnd)
{
int id;
HMENU hMenuMain = GetMenu(hWnd);
HMENU hMenuView = GetSubMenu(hMenuMain,idmView);
int nDiff = idmViewMax - GetMenuItemCount(hMenuView); // in case stuff was deleted off this menu
HMENU hMenu = GetSubMenu(hMenuView, idmSortBy - nDiff);
BOOL bRet;
//
// There are several menus to update here ...
// Sort by TEXT("Column")
// Sort by FirstName or LastName
// Sort Ascending or descending
switch(bwi_SortInfo.iOldSortCol)
{
case colDisplayName:
id = IDM_VIEW_SORTBY_DISPLAYNAME;
break;
case colEmailAddress:
id = IDM_VIEW_SORTBY_EMAILADDRESS;
break;
case colOfficePhone:
id = IDM_VIEW_SORTBY_BUSINESSPHONE;
break;
case colHomePhone:
id = IDM_VIEW_SORTBY_HOMEPHONE;
break;
}
bRet = CheckMenuRadioItem( hMenu,
IDM_VIEW_SORTBY_DISPLAYNAME,
IDM_VIEW_SORTBY_HOMEPHONE,
id,
MF_BYCOMMAND);
if (id!=IDM_VIEW_SORTBY_DISPLAYNAME)
{
EnableMenuItem(hMenu,IDM_VIEW_SORTBY_LASTNAME,MF_BYCOMMAND | MF_GRAYED);
EnableMenuItem(hMenu,IDM_VIEW_SORTBY_FIRSTNAME,MF_BYCOMMAND | MF_GRAYED);
}
else
{
EnableMenuItem(hMenu,IDM_VIEW_SORTBY_LASTNAME,MF_BYCOMMAND | MF_ENABLED);
EnableMenuItem(hMenu,IDM_VIEW_SORTBY_FIRSTNAME,MF_BYCOMMAND | MF_ENABLED);
}
id = (bwi_SortInfo.bSortByLastName) ? IDM_VIEW_SORTBY_LASTNAME : IDM_VIEW_SORTBY_FIRSTNAME;
bRet = CheckMenuRadioItem( hMenu,
IDM_VIEW_SORTBY_FIRSTNAME,
IDM_VIEW_SORTBY_LASTNAME,
id,
MF_BYCOMMAND);
id = (bwi_SortInfo.bSortAscending) ? IDM_VIEW_SORTBY_ASCENDING : IDM_VIEW_SORTBY_DESCENDING;
bRet = CheckMenuRadioItem( hMenu,
IDM_VIEW_SORTBY_ASCENDING,
IDM_VIEW_SORTBY_DESCENDING,
id,
MF_BYCOMMAND);
return;
}
///////////////////////////////////////////////////////////////////////////
//
// Updates the toolbar based on the contents of the list box
//
//
///////////////////////////////////////////////////////////////////////////
void UpdateToolbarAndMenu(LPBWI lpbwi)
{
//
// Toolbar Button States
//
// Y: Enabled
// N: Disabled
//
// non-Empty-WAB Empty-WAB non-EmptyLDAP EmptyLDAP
// New Y Y N N
// Properties Y N Y N
// Delete Y N N N
// Search Y Y Y Y
// Add to WAB N N Y N
// Print Y N Y N
// SendMail Y N Y N
BOOL bState[tbMAX];
int i;
// if the current focus is on a group, all the above can be selected
// else depends on the list view
if(bIsFocusOnTV(lpbwi))
{
for(i=0;i<tbMAX;i++)
bState[i] = TRUE;
// if there are no items in this group, tag it so
if(ListView_GetItemCount(bwi_hWndListAB) <= 0)
bState[tbPrint] = /*bState[tbAction] =*/ FALSE;
// [PaulHi] 11/23/98 Raid #12453
// Allow pasting into the Tree View
// bState[tbCopy] = bState[tbPaste] = FALSE;
bState[tbCopy] = FALSE;
bState[tbPaste] = bIsPasteData();
}
else
{
GetCurrentOptionsState( NULL, bwi_hWndListAB, bState);
}
// if( (bDoesThisWABHaveAnyUsers(bwi_lpIAB)) &&
// TreeView_GetSelection(bwi_hWndTV) == TreeView_GetRoot(bwi_hWndTV))
// bState[tbNewFolder] = FALSE;
// Set the toolbar button states
SendMessage(bwi_hWndBB,WM_PRVATETOOLBARENABLE,(WPARAM) IDC_BB_NEW,(LPARAM) MAKELONG(bState[tbNew], 0));
SendMessage(bwi_hWndBB,WM_PRVATETOOLBARENABLE,(WPARAM) IDC_BB_PROPERTIES,(LPARAM) MAKELONG(bState[tbProperties], 0));
SendMessage(bwi_hWndBB,WM_PRVATETOOLBARENABLE,(WPARAM) IDC_BB_DELETE,(LPARAM) MAKELONG(bState[tbDelete], 0));
SendMessage(bwi_hWndBB,WM_PRVATETOOLBARENABLE,(WPARAM) IDC_BB_FIND,(LPARAM) MAKELONG(bState[tbFind], 0));
SendMessage(bwi_hWndBB,WM_PRVATETOOLBARENABLE,(WPARAM) IDC_BB_PRINT,(LPARAM) MAKELONG(bState[tbPrint], 0));
SendMessage(bwi_hWndBB,WM_PRVATETOOLBARENABLE,(WPARAM) IDC_BB_ACTION,(LPARAM) MAKELONG(bState[tbAction], 0));
#ifdef WIN16 // WIN16FF:Disable find button of coolbar. Find is not beta1 feature
SendMessage(bwi_hWndBB,WM_PRVATETOOLBARENABLE,(WPARAM) IDC_BB_FIND,(LPARAM)MAKELONG(0, 0));
#endif
//
// We also need to synchronize the menus with the toolbar ...
//
{
HMENU hMenuMain = GetMenu(bwi_hWndAB);
HMENU hMenuSub = GetSubMenu(hMenuMain,idmFile);
UINT uiFlag[tbMAX];
for(i=0;i<tbMAX;i++)
uiFlag[i] = (bState[i] ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(hMenuSub,IDM_FILE_NEWCONTACT,MF_BYCOMMAND | uiFlag[tbNewEntry]);
EnableMenuItem(hMenuSub,IDM_FILE_NEWGROUP, MF_BYCOMMAND | uiFlag[tbNewGroup]);
EnableMenuItem(hMenuSub,IDM_FILE_NEWFOLDER, MF_BYCOMMAND | uiFlag[tbNewFolder]);
EnableMenuItem(hMenuSub,IDM_FILE_DELETE, MF_BYCOMMAND | uiFlag[tbDelete]);
EnableMenuItem(hMenuSub,IDM_FILE_PROPERTIES,MF_BYCOMMAND | uiFlag[tbProperties]);
//EnableMenuItem(hMenuSub,IDM_FILE_ADDTOWAB, MF_BYCOMMAND | uiFlag[tbAddToWAB]);
//EnableMenuItem(hMenuSub,IDM_FILE_SENDMAIL, MF_BYCOMMAND | uiFlag[tbAction]);
if(bPrintingOn)
EnableMenuItem(hMenuSub,IDM_FILE_PRINT, MF_BYCOMMAND | uiFlag[tbPrint]);
hMenuSub = GetSubMenu(hMenuMain,idmEdit);
EnableMenuItem(hMenuSub,IDM_EDIT_COPY, MF_BYCOMMAND | uiFlag[tbCopy]);
EnableMenuItem(hMenuSub,IDM_EDIT_PASTE, MF_BYCOMMAND | uiFlag[tbPaste]);
#ifdef WIN16 // WIN16FF:FIND is not beta1 feature
EnableMenuItem(hMenuSub,IDM_EDIT_FIND, MF_BYCOMMAND | MF_GRAYED);
#else
EnableMenuItem(hMenuSub,IDM_EDIT_FIND, MF_BYCOMMAND | uiFlag[tbFind]);
#endif
//hMenuSub = GetSubMenu(hMenuMain,idmTools);
}
ShowLVCountinStatusBar(lpbwi);
return;
}
//$$//////////////////////////////////////////////////////////////////////////////
//
// SaveCurrentPosition
//
// Saves the modeless dialog window position and the list view column sizes ...
//
//////////////////////////////////////////////////////////////////////////////////
void SaveCurrentPosition(LPBWI lpbwi, HWND hWnd, HWND hWndLV, HWND hWndTB, HWND hWndSB)
{
ABOOK_POSCOLSIZE ABPosColSize = {0};
int i;
RECT rect;
//
// First read the previous settings from the registry so we dont
// overwrite something if we dont need to ...
//
ReadRegistryPositionInfo(bwi_lpIAB, &ABPosColSize, lpszRegPositionKeyValueName);
{
WINDOWPLACEMENT wpl = {0};
wpl.length = sizeof(WINDOWPLACEMENT);
// This call tells us the window state and normal size and position
GetWindowPlacement(hWnd, &wpl);
// There seems to be a bug in GetWindowPlacement that
// doesnt account for various taskbars on the screen when
// returning the Window's Normal Position .. as a result
// the stored coordinates won't be accurate. Instead, we'll
// use those coordinates only if the window is maximized or
// minimized - otherwise we will use the GetWindowRect
// coordinates.
// Get the screen position of this window
GetWindowRect(hWnd, &(ABPosColSize.rcPos));
if(wpl.showCmd != SW_SHOWNORMAL)
{
ABPosColSize.rcPos = wpl.rcNormalPosition;
}
}
// Check the current List View Style
ABPosColSize.dwListViewStyle = GetWindowLong(hWndLV, GWL_STYLE);
if( (ABPosColSize.dwListViewStyle & LVS_TYPEMASK) == LVS_REPORT )
{
ABPosColSize.nListViewStyleMenuID = IDM_VIEW_DETAILS;
// get column widths only if this is the details style otherwise
// not ...
for(i=0; i<NUM_COLUMNS; i++)
{
int nCol = ListView_GetColumnWidth(hWndLV, i);
if(nCol!=0)
ABPosColSize.nColWidth[i] = nCol;
}
}
else if( (ABPosColSize.dwListViewStyle & LVS_TYPEMASK) == LVS_SMALLICON )
ABPosColSize.nListViewStyleMenuID = IDM_VIEW_SMALLICON;
else if( (ABPosColSize.dwListViewStyle & LVS_TYPEMASK) == LVS_ICON )
ABPosColSize.nListViewStyleMenuID = IDM_VIEW_LARGEICON;
else if( (ABPosColSize.dwListViewStyle & LVS_TYPEMASK) == LVS_LIST )
ABPosColSize.nListViewStyleMenuID = IDM_VIEW_LIST;
if (IsWindowVisible(hWndTB))
ABPosColSize.bViewToolbar = TRUE;
else
ABPosColSize.bViewToolbar = FALSE;
if (IsWindowVisible(hWndSB))
ABPosColSize.bViewStatusBar = TRUE;
else
ABPosColSize.bViewStatusBar = FALSE;
{
if (IsWindowVisible(bwi_hWndTV))
ABPosColSize.bViewGroupList = TRUE;
else
ABPosColSize.bViewGroupList = FALSE;
}
ListView_GetColumnOrderArray(hWndLV, NUM_COLUMNS, ABPosColSize.colOrderArray);
GetWindowRect( bwi_hWndTV, &rect );
ABPosColSize.nTViewWidth = rect.right - rect.left;
WriteRegistryPositionInfo(bwi_lpIAB, &ABPosColSize,lpszRegPositionKeyValueName);
return;
}
//$$//////////////////////////////////////////////////////////////////////////////
//
// SetPreviousSessionPosition
//
// Sets the modeless dialog window position and the list view column sizes based on
// the previous sessions parameters ...
//
//////////////////////////////////////////////////////////////////////////////////
void SetPreviousSessionPosition(LPBWI lpbwi, HWND hWnd, HWND hWndLV, HWND hWndTB, HWND hWndSB)
{
ABOOK_POSCOLSIZE ABPosColSize = {0};
int i;
RECT rect;
ABPosColSize.bViewGroupList =TRUE; // Off by default
if(ReadRegistryPositionInfo(bwi_lpIAB, &ABPosColSize, lpszRegPositionKeyValueName))
{
rect.left = ABPosColSize.rcPos.left;
rect.top = ABPosColSize.rcPos.top;
rect.right = ABPosColSize.rcPos.right;
rect.bottom = ABPosColSize.rcPos.bottom;
if( IsWindowOnScreen( &rect ) )
{
MoveWindow(hWnd,
ABPosColSize.rcPos.left,
ABPosColSize.rcPos.top,
ABPosColSize.rcPos.right-ABPosColSize.rcPos.left,
ABPosColSize.rcPos.bottom-ABPosColSize.rcPos.top,
FALSE);
}
for(i=0; i<NUM_COLUMNS; i++)
{
if(ABPosColSize.nColWidth[i]!=0)
ListView_SetColumnWidth(hWndLV, i, ABPosColSize.nColWidth[i]);
}
if(ABPosColSize.bViewToolbar == FALSE)
{
//hide it
CheckMenuItem(GetMenu(hWnd),IDM_VIEW_TOOLBAR,MF_BYCOMMAND | MF_UNCHECKED);
ShowWindow(hWndTB, SW_HIDE);
}
if(ABPosColSize.bViewStatusBar == FALSE)
{
//hide it
CheckMenuItem(GetMenu(hWnd),IDM_VIEW_STATUSBAR,MF_BYCOMMAND | MF_UNCHECKED);
ShowWindow(hWndSB, SW_HIDE);
}
GetWindowRect( bwi_hWndTV, &rect );
if( ABPosColSize.nTViewWidth != 0 )
MoveWindow( bwi_hWndTV, rect.left, rect.top, ABPosColSize.nTViewWidth, rect.bottom - rect.top, FALSE );
ResizeAddressBookChildren(lpbwi, hWnd);//,SIZE_RESTORED);
if (ABPosColSize.nListViewStyleMenuID != 0)
{
SetListViewStyle(lpbwi, ABPosColSize.nListViewStyleMenuID);
CheckMenuRadioItem( GetMenu(hWnd),
IDM_VIEW_LARGEICON,
IDM_VIEW_DETAILS,
ABPosColSize.nListViewStyleMenuID,
MF_BYCOMMAND);
}
{
int nTotal=0,nColSum=0;
// the previous version did not have the column order setting, so if the
// values are incorrect reset them
for(i=0;i<NUM_COLUMNS;i++)
{
nTotal += ABPosColSize.colOrderArray[i];
nColSum += i;
}
if(nColSum != nTotal)
{
for(i=0;i<NUM_COLUMNS;i++)
ABPosColSize.colOrderArray[i] = i;
}
}
ListView_SetColumnOrderArray(hWndLV, NUM_COLUMNS, ABPosColSize.colOrderArray);
}
if(ABPosColSize.bViewGroupList == FALSE)
{
//hide it
CheckMenuItem(GetMenu(hWnd),IDM_VIEW_GROUPSLIST,MF_BYCOMMAND | MF_UNCHECKED);
ShowWindow(bwi_hWndTV, SW_HIDE);
ShowWindow(bwi_hWndSplitter, SW_HIDE);
InvalidateRect(bwi_hWndStaticQF, NULL, TRUE);
// folder not on the Shared Contacts
if(bIsThereACurrentUser(bwi_lpIAB))
{
LPSBinary lpsbSelection = &bwi_lpIAB->lpWABCurrentUserFolder->sbEID;
UpdateTVGroupSelection(bwi_hWndTV, lpsbSelection);
}
else
{
// Set the selection to the root address book so we see the file
// contents just as if we dont have a treeview at all
TreeView_SelectItem(bwi_hWndTV, TreeView_GetRoot(bwi_hWndTV));
}
}
return;
}
#define MAX_TOOLTIP_LENGTH 300
#define TOOLTIP_INITTIME 5000 //milliseconds
#define TOOLTIP_TIME 8000 //milliseconds
//$$/////////////////////////////////////////////////////////////////////////////
//
// void UpdateTooltipTextBuffer - Updates the text in the buffer for the tooltip
//
////////////////////////////////////////////////////////////////////////////////
void UpdateTooltipTextBuffer(LPBWI lpbwi, int nItem)
{
LPTSTR lpszData = NULL;
bwi_tt_iItem = nItem;
bwi_tt_szTipText[0]='\0';
HrGetLVItemDataString(bwi_lpAdrBook, bwi_hWndListAB, nItem, &lpszData);
if(lpszData)
{
if (CharSizeOf(bwi_tt_szTipText) < (lstrlen(lpszData)+1))
{
LPTSTR lpsz = TEXT(" ...");
ULONG nLen = TruncatePos(lpszData, CharSizeOf(bwi_tt_szTipText) - lstrlen(lpsz) - 1);
CopyMemory(bwi_tt_szTipText, lpszData, sizeof(TCHAR)*nLen);
bwi_tt_szTipText[nLen]='\0';
StrCatBuff(bwi_tt_szTipText,lpsz, ARRAYSIZE(bwi_tt_szTipText));
}
else
StrCpyN(bwi_tt_szTipText, lpszData, ARRAYSIZE(bwi_tt_szTipText));
}
LocalFreeAndNull(&lpszData);
return;
}
//$$/////////////////////////////////////////////////////////////////////////////
//
// void InitMultiLineTooltip - initializes the multiline tooltip for the list view
// control
//
////////////////////////////////////////////////////////////////////////////////
void InitMultiLineToolTip(LPBWI lpbwi, HWND hWndParent)
{
TOOLINFO ti = {0};
bwi_tt_bActive = FALSE;
bwi_tt_iItem = -1;
bwi_tt_szTipText[0]='\0';
FillTooltipInfo(lpbwi, &ti);
SendMessage(bwi_hWndTT, TTM_SETMAXTIPWIDTH, 0, (LPARAM) MAX_TOOLTIP_LENGTH);
ToolTip_AddTool(bwi_hWndTT, (LPARAM) (LPTOOLINFO) &ti);
SendMessage(bwi_hWndTT, TTM_SETDELAYTIME, (WPARAM) TTDT_INITIAL, (LPARAM) TOOLTIP_INITTIME);
SendMessage(bwi_hWndTT, TTM_SETDELAYTIME, (WPARAM) TTDT_RESHOW, (LPARAM) TOOLTIP_INITTIME);
SendMessage(bwi_hWndTT, TTM_SETDELAYTIME, (WPARAM) TTDT_AUTOPOP, (LPARAM) TOOLTIP_TIME);
SendMessage(bwi_hWndTT, TTM_ACTIVATE, (WPARAM) TRUE, 0);
if(!bwi_tt_bActive)
{
// if the tooltip is not active, activate it
TOOLINFO ti = {0};
FillTooltipInfo(lpbwi, &ti);
ti.lpszText = szEmpty; //LPSTR_TEXTCALLBACK;
ToolTip_UpdateTipText(bwi_hWndTT, (LPARAM)&ti);
SendMessage(bwi_hWndTT, TTM_TRACKACTIVATE,(WPARAM)TRUE,(LPARAM)&ti);
bwi_tt_bActive = TRUE;
}
return;
}
//$$/////////////////////////////////////////////////////////////////////////////
//
// void FillTooltipInfo - initializes the tooltip structure for making updates or
// modifications to the tooltips
//
////////////////////////////////////////////////////////////////////////////////
void FillTooltipInfo(LPBWI lpbwi, LPTOOLINFO lpti)
{
lpti->cbSize = sizeof(TOOLINFO);
lpti->hwnd = bwi_hWndAB;
lpti->uId = (UINT_PTR) bwi_hWndListAB;
lpti->hinst = hinstMapiX;
lpti->uFlags = TTF_IDISHWND | TTF_SUBCLASS;// | TTF_ABSOLUTE | TTF_TRACK;
lpti->lpszText = szEmpty;//LPSTR_TEXTCALLBACK;
lpti->lParam = 0;
return;
}
//$$/////////////////////////////////////////////////////////////////////////////
//
// int HitTestLVSelectedItem() - Gets the item index number of the item exactly under
// the mouse - further selects the item if it isnt selected
//
////////////////////////////////////////////////////////////////////////////////
int HitTestLVSelectedItem(LPBWI lpbwi)
{
POINT pt;
RECT rc;
int nItemIndex = -1;
LV_HITTESTINFO lht = {0};
GetCursorPos(&pt);
GetWindowRect(bwi_hWndListAB, &rc);
lht.pt.x = pt.x - rc.left;
lht.pt.y = pt.y - rc.top;
ListView_HitTest(bwi_hWndListAB, &lht);
if(lht.iItem != -1)
nItemIndex = lht.iItem;
return nItemIndex;
}
/***********************************************************
Handle_WM_INITMENUPOPUP
Handles any popup menu's we need to modify ..
***********************************************************/
void Handle_WM_INITMENUPOPUP (HWND hWnd, LPBWI lpbwi, UINT message, WPARAM uParam, LPARAM lParam )
{
HMENU hMenuPopup = (HMENU) uParam;
UINT uPos = (UINT) LOWORD(lParam);
BOOL fSysMenu = (BOOL) HIWORD(lParam);
// Look at the first item on the menu to identify it
UINT uID = GetMenuItemID(hMenuPopup, 0);
if(uID == IDM_FILE_SENDMAIL) // this is the Tools | Action Menu
{
AddExtendedMenuItems(bwi_lpAdrBook, bwi_hWndListAB,
hMenuPopup, TRUE,
(!bIsFocusOnTV(lpbwi))); // this is the condition for updating SendMailTo
}
else
if(uID == IDM_EDIT_COPY)
{
UpdateToolbarAndMenu(lpbwi);
}
else
if(uID == IDM_FILE_NEWCONTACT)
{
if(bDoesThisWABHaveAnyUsers(bwi_lpIAB))
UpdateViewFoldersMenu(lpbwi, hWnd);
}
UpdateSynchronizeMenus(hMenuPopup, bwi_lpIAB);
/*
else if(uID == IDM_FILE_NEWCONTACT)
{
if(!bIsThereACurrentUser(bwi_lpIAB))
EnableMenuItem(hMenuPopup, IDM_FILE_SWITCHUSERS, MF_GRAYED | MF_BYCOMMAND);
}
*/
}
/***********************************************************
The Handle_WM_MENSELECT function below is a pared down
cheezy sample to figure out the ID of the currently selected
menu. It returns 0 if a popup menu is selected, -1 of no menu
is selected (i.e. closed), and a positive nonzero value
if a menu item is selected.
***********************************************************/
void Handle_WM_MENSELECT (LPBWI lpbwi, UINT message, WPARAM uParam, LPARAM lParam )
{
UINT nStringID = 0;
TCHAR sz[MAX_UI_STR];
UINT fuFlags = (UINT)HIWORD(uParam) & 0xffff;
UINT uCmd = (UINT)LOWORD(uParam);
HMENU hMenu = (HMENU)lParam;
nStringID = 0;
sz[0] = TEXT('\0');
if (fuFlags == 0xffff && hMenu == NULL) // Menu has been closed
nStringID = (UINT)-1;
else if (fuFlags & MFT_SEPARATOR) // Ignore separators
nStringID = 0;
else if (fuFlags & MF_POPUP) // Popup menu
{
nStringID = 0;
if (fuFlags & MF_SYSMENU) // System menu
nStringID = 0;
} // for MF_POPUP
else // Must be a command item
{
switch(uCmd)
{
case IDC_BB_PRINT:
case IDM_FILE_PRINT:
nStringID = idsPrintMenu;
break;
case IDM_VIEW_GROUPSLIST:
nStringID = idsGroupListMenu;
break;
case IDM_HELP_ABOUTADDRESSBOOK:
nStringID = idsAboutMenu;
break;
case IDM_LVCONTEXT_NEWCONTACT:
case IDM_FILE_NEWCONTACT:
nStringID = idsMenuNewContact;
break;
case IDM_LVCONTEXT_NEWGROUP:
case IDM_FILE_NEWGROUP:
nStringID = idsMenuNewGroup;
break;
case IDM_LVCONTEXT_NEWFOLDER:
case IDM_FILE_NEWFOLDER:
nStringID = idsMenuNewFolder;
break;
case IDM_LVCONTEXT_COPY:
case IDM_EDIT_COPY:
nStringID = idsMenuCopy;
break;
case IDM_LVCONTEXT_PASTE:
case IDM_EDIT_PASTE:
nStringID = idsMenuPaste;
break;
case IDM_LVCONTEXT_PROPERTIES:
case IDM_FILE_PROPERTIES:
nStringID = idsMenuProperties;
break;
case IDM_LVCONTEXT_DELETE:
case IDM_FILE_DELETE:
nStringID = idsMenuDeleteRemove;
break;
//case IDM_FILE_ADDTOWAB:
//case IDM_LVCONTEXT_ADDTOWAB:
// nStringID = idsMenuAddToWAB;
// break;
case IDM_LVCONTEXT_FIND:
case IDM_EDIT_FIND:
nStringID = idsMenuFind;
break;
case IDM_FILE_DIRECTORY_SERVICE:
nStringID = idsMenuDirectoryService;
break;
case IDM_FILE_SWITCHUSERS:
nStringID = idsMenuSwitchUser;
break;
case IDM_FILE_SHOWALLCONTENTS:
nStringID = idsMenuShowAllContents;
break;
case IDM_FILE_EXIT:
nStringID = idsMenuExit;
break;
case IDM_EDIT_SELECTALL:
nStringID = idsMenuSelectAll;
break;
case IDM_VIEW_TOOLBAR:
nStringID = idsMenuViewToolbar;
break;
case IDM_VIEW_STATUSBAR:
nStringID = idsMenuViewStatusBar;
break;
case IDM_VIEW_LARGEICON:
nStringID = idsMenuLargeIcon;
break;
case IDM_VIEW_SMALLICON:
nStringID = idsMenuSmallIcon;
break;
case IDM_VIEW_LIST:
nStringID = idsMenuList;
break;
case IDM_VIEW_DETAILS:
nStringID = idsMenuDetails;
break;
case IDM_VIEW_SORTBY_DISPLAYNAME:
nStringID = idsMenuDisplayName;
break;
case IDM_VIEW_SORTBY_EMAILADDRESS:
nStringID = idsMenuEmail;
break;
case IDM_VIEW_SORTBY_BUSINESSPHONE:
nStringID = idsMenuBusinessPhone;
break;
case IDM_VIEW_SORTBY_HOMEPHONE:
nStringID = idsMenuHomePhone;
break;
case IDM_VIEW_SORTBY_FIRSTNAME:
nStringID = idsMenuFirstName;
break;
case IDM_VIEW_SORTBY_LASTNAME:
nStringID = idsMenuLastName;
break;
case IDM_VIEW_SORTBY_ASCENDING:
nStringID = idsMenuAscending;
break;
case IDM_VIEW_SORTBY_DESCENDING:
nStringID = idsMenuDescending;
break;
case IDM_VIEW_REFRESH:
nStringID = idsMenuRefresh;
break;
case IDM_TOOLS_IMPORT_WAB:
nStringID = idsMenuImportWAB;
break;
case IDM_TOOLS_IMPORT_VCARD:
nStringID = idsMenuImportVcard;
break;
case IDM_TOOLS_IMPORT_OTHER:
nStringID = idsMenuImportOther;
break;
case IDM_TOOLS_EXPORT_OTHER:
nStringID = idsMenuExportOther;
break;
case IDM_TOOLS_EXPORT_WAB:
nStringID = idsMenuExportWAB;
break;
case IDM_TOOLS_EXPORT_VCARD:
nStringID = idsMenuExportVcard;
break;
case IDM_HELP_ADDRESSBOOKHELP:
nStringID = idsMenuHelp;
break;
case IDM_EDIT_SETME:
nStringID = idsMenuEditProfile;
break;
default:
nStringID = 0;
GetContextMenuExtCommandString(bwi_lpIAB, uCmd, sz, CharSizeOf(sz));
break;
}
}
if (nStringID > 0)
{
LoadString(hinstMapiX, nStringID, sz, ARRAYSIZE(sz));
}
StatusBarMessage(lpbwi, sz);
return;
}
//$$////////////////////////////////////////////////////////////////////////////////////////
//
// Fills a lpList from the contents of a given group
// If lpList is NULL, ignores that parameter
// If lpszName is NULL, ignores that parameter
//
//////////////////////////////////////////////////////////////////////////////////////////
HRESULT FillListFromGroup(
LPADRBOOK lpAdrBook,
ULONG cbGroupEntryID,
LPENTRYID lpGroupEntryID,
LPTSTR lpszName,
ULONG cchName,
LPRECIPIENT_INFO * lppList)
{
ULONG ulcPropCount;
LPSPropValue lpPropArray = NULL;
ULONG j;
HRESULT hr = E_FAIL;
LPRECIPIENT_INFO lpInfo = NULL;
hr = HrGetPropArray( lpAdrBook, NULL,
cbGroupEntryID, (LPENTRYID) lpGroupEntryID,
MAPI_UNICODE,
&ulcPropCount, &lpPropArray);
if (HR_FAILED(hr))
goto exit;
if(lppList && *lppList)
FreeRecipList(lppList);
for(j=0;j<ulcPropCount;j++)
{
// We are ignoring PR_WAB_DL_ONEOFFS here since we don't want to show OneOffs
if( lpPropArray[j].ulPropTag==PR_WAB_DL_ENTRIES && lppList )
{
ULONG k;
// Look at each entry in the PR_WAB_DL_ENTRIES and recursively check it.
for (k = 0; k < lpPropArray[j].Value.MVbin.cValues; k++)
{
ULONG cbEID = lpPropArray[j].Value.MVbin.lpbin[k].cb;
{
LPENTRYID lpEID = (LPENTRYID)lpPropArray[j].Value.MVbin.lpbin[k].lpb;
// we don't want one-offs showing up in the UI because all kinds of problems start happening
// when these one-offs are dragged and dropped
// A doublecheck here not really needed in 99% cases
if(WAB_ONEOFF == IsWABEntryID(cbEID, lpEID, NULL, NULL, NULL, NULL, NULL))
continue;
ReadSingleContentItem( lpAdrBook,cbEID, (LPENTRYID)lpEID, &lpInfo);
if(lpInfo)
{
lpInfo->lpNext = *lppList;
if(*lppList)
(*lppList)->lpPrev = lpInfo;
*lppList = lpInfo;
}
}
}
}
else if (lpPropArray[j].ulPropTag == PR_DISPLAY_NAME)
{
if(lpszName)
StrCpyN(lpszName, lpPropArray[j].Value.LPSZ, cchName);
}
}
hr = S_OK;
exit:
if(lpPropArray)
MAPIFreeBuffer(lpPropArray);
return(hr);
}
//$$////////////////////////////////////////////////////////////////////////////////////////
//
// UpdateListViewContents(lpsbEID)
//
// Updates the displayed list in the list view based on the entry id of the selected
// TreeView item
//
//////////////////////////////////////////////////////////////////////////////////////////
void UpdateListViewContents(LPBWI lpbwi, LPSBinary lpsbEID, ULONG ulObjectType)
{
LPPTGDATA lpPTGData=GetThreadStoragePointer();
if( (ulObjectType == MAPI_ABCONT && (pt_bIsWABOpenExSession || bIsWABSessionProfileAware(bwi_lpIAB)))//a folder and it's outlook or profiles are enabled
|| !lpsbEID || !lpsbEID->cb || !lpsbEID->lpb )// or no container entryid
{
HrGetWABContents( bwi_hWndListAB,
bwi_lpAdrBook,
lpsbEID,
bwi_SortInfo,
&(bwi_lpContentsList));
}
else if(ulObjectType == MAPI_DISTLIST )
{
if(!HR_FAILED( FillListFromGroup(
bwi_lpAdrBook,
lpsbEID->cb,
(LPENTRYID) lpsbEID->lpb,
NULL,
0,
&(bwi_lpContentsList))))
{
int nSelectedItem = ListView_GetNextItem(bwi_hWndListAB, -1, LVNI_SELECTED);
if(nSelectedItem < 0)
nSelectedItem = 0;
ListView_DeleteAllItems(bwi_hWndListAB);
if (!HR_FAILED(HrFillListView( bwi_hWndListAB,
bwi_lpContentsList)))
{
SendMessage(bwi_hWndListAB, WM_SETREDRAW, FALSE, 0);
SortListViewColumn(bwi_lpIAB, bwi_hWndListAB, colDisplayName, &bwi_SortInfo, TRUE);
SendMessage(bwi_hWndListAB, WM_SETREDRAW, TRUE, 0);
}
if(nSelectedItem >= ListView_GetItemCount(bwi_hWndListAB))
nSelectedItem = ListView_GetItemCount(bwi_hWndListAB)-1;
LVSelectItem(bwi_hWndListAB, nSelectedItem);
}
}
ShowLVCountinStatusBar(lpbwi);
return;
}
//$$////////////////////////////////////////////////////////////////////////////////////////
//
// UpdateTVGroupSelection(HWND hWndTV, lpsbSelectEID)
//
// Updates the selected item on the TreeView to point to the item having the given
// entryid
//
//////////////////////////////////////////////////////////////////////////////////////////
void UpdateTVGroupSelection(HWND hWndTV, LPSBinary lpsbSelectEID)
{
// search for the specified group and select it ..
HTREEITEM hRoot = TreeView_GetRoot(hWndTV);
if(!lpsbSelectEID || !lpsbSelectEID->cb || !lpsbSelectEID->lpb)
{
//if(!bIsSelectedTVContainer(lpbwi))
TreeView_SelectItem(hWndTV, hRoot); //Select the Address Book
}
else
{
BOOL bSet = FALSE;
TV_ITEM tvI = {0};
tvI.mask = TVIF_PARAM | TVIF_HANDLE;
while(hRoot && !bSet)
{
HTREEITEM hItem = TreeView_GetChild(hWndTV, hRoot);
tvI.hItem = hRoot;
TreeView_GetItem(hWndTV, &tvI);
if(tvI.lParam)
{
LPTVITEM_STUFF lptvStuff = (LPTVITEM_STUFF) tvI.lParam;
if( lptvStuff && lptvStuff->lpsbEID && lptvStuff->lpsbEID->cb &&
!memcmp(lptvStuff->lpsbEID->lpb,lpsbSelectEID->lpb,lpsbSelectEID->cb))
{
TreeView_SelectItem(hWndTV, hRoot);
break;
}
}
while(hItem)
{
tvI.hItem = hItem;
TreeView_GetItem(hWndTV, &tvI);
if(tvI.lParam)
{
LPTVITEM_STUFF lptvStuff = (LPTVITEM_STUFF) tvI.lParam;
if( lptvStuff && lptvStuff->lpsbEID && lptvStuff->lpsbEID->cb &&
!memcmp(lptvStuff->lpsbEID->lpb,lpsbSelectEID->lpb,lpsbSelectEID->cb))
{
bSet = TRUE;
TreeView_SelectItem(hWndTV, hItem); //Select the Address Book
break;
}
}
hItem = TreeView_GetNextSibling(hWndTV, hItem);
}
hRoot = TreeView_GetNextSibling(hWndTV, hRoot);
}
}
return;
}
//$$////////////////////////////////////////////////////////////////////////////////////////
//
// Checks if the currently selected tree view item is a container item
// Returns true if it is a container item .. this way we can distinguish between
// groups and folders/containers
//
//////////////////////////////////////////////////////////////////////////////////////////
BOOL bIsSelectedTVContainer(LPBWI lpbwi)
{
HTREEITEM hItem = bwi_hti ? bwi_hti : TreeView_GetSelection(bwi_hWndTV);
TV_ITEM tvI = {0};
tvI.mask = TVIF_PARAM | TVIF_HANDLE;
tvI.hItem = hItem;
TreeView_GetItem(bwi_hWndTV, &tvI);
if(tvI.lParam)
return (((LPTVITEM_STUFF)tvI.lParam)->ulObjectType==MAPI_ABCONT);
return TRUE;
}
//$$////////////////////////////////////////////////////////////////////////////////////////
//
// Checks if the focus is on the TreeView or not
//
//////////////////////////////////////////////////////////////////////////////////////////
BOOL bIsFocusOnTV(LPBWI lpbwi)
{
return( IsWindowVisible(bwi_hWndTV) && (bwi_iFocus == s_TV));
}
//$$////////////////////////////////////////////////////////////////////////////////////////
//
// Gets EntryID of CurrentSelection
// lpcbEID, lppEID should be MAPIFreeBuffered
//
// bTopMost means that get the EntryID of the topmost parent of a given selection in case the
// selection is on a sub-item
//
//////////////////////////////////////////////////////////////////////////////////////////
void GetCurrentSelectionEID(LPBWI lpbwi, HWND hWndTV, LPSBinary * lppsbEID, ULONG * lpulObjectType, BOOL bTopMost)
{
HTREEITEM hItem = bwi_hti ? bwi_hti : TreeView_GetSelection(hWndTV);
TV_ITEM tvI = {0};
LPSBinary lpsbEID = NULL;
if(!lppsbEID)
return;
*lppsbEID = NULL;
if(bTopMost)
{
HTREEITEM hParent = NULL;
while(hParent = TreeView_GetParent(hWndTV, hItem))
hItem = hParent;
}
tvI.mask = TVIF_PARAM | TVIF_HANDLE;
tvI.hItem = hItem;
if(TreeView_GetItem(hWndTV, &tvI))
{
if(tvI.lParam)
{
LPTVITEM_STUFF lptvStuff = (LPTVITEM_STUFF) tvI.lParam;
if(lptvStuff)
{
if(lptvStuff->lpsbEID)
{
lpsbEID = LocalAlloc(LMEM_ZEROINIT, sizeof(SBinary));
if(lpsbEID)
{
if(lptvStuff->lpsbEID->cb)
SetSBinary(lpsbEID, lptvStuff->lpsbEID->cb, lptvStuff->lpsbEID->lpb);
*lppsbEID = lpsbEID;
}
if(lpulObjectType)
*lpulObjectType = lptvStuff->ulObjectType;
}
}
}
}
return;
}
//$$////////////////////////////////////////////////////////////////////////////////////////
//
// Removes specified group from WAB
//
//////////////////////////////////////////////////////////////////////////////////////////
HRESULT HrRemoveEntryFromWAB(LPIAB lpIAB, ULONG cbEID, LPENTRYID lpEID)
{
HRESULT hr = hrSuccess;
ULONG cbWABEID = 0;
LPENTRYID lpWABEID = NULL;
LPABCONT lpWABCont = NULL;
ULONG ulObjType;
SBinaryArray SBA;
SBinary SB;
hr = lpIAB->lpVtbl->GetPAB(lpIAB,&cbWABEID,&lpWABEID);
if(HR_FAILED(hr))
goto out;
hr = lpIAB->lpVtbl->OpenEntry(lpIAB,
cbWABEID, // size of EntryID to open
lpWABEID, // EntryID to open
NULL, // interface
0, // flags
&ulObjType,
(LPUNKNOWN *)&lpWABCont);
if(HR_FAILED(hr))
goto out;
SB.cb = cbEID;
SB.lpb = (LPBYTE) lpEID;
SBA.cValues = 1;
SBA.lpbin = &SB;
hr = lpWABCont->lpVtbl->DeleteEntries(
lpWABCont,
(LPENTRYLIST) &SBA,
0);
if(HR_FAILED(hr))
goto out;
out:
if(lpWABCont)
UlRelease(lpWABCont);
if(lpWABEID)
FreeBufferAndNull(&lpWABEID);
return hr;
}
//$$////////////////////////////////////////////////////////////////////////////////////
//
// FreeTVItemLParam
//
//
////////////////////////////////////////////////////////////////////////////////////////
void FreeTVItemLParam(HWND hWndTV, HTREEITEM hItem)
{
TV_ITEM tvI = {0};
tvI.mask = TVIF_PARAM | TVIF_HANDLE;
tvI.hItem = hItem;
TreeView_GetItem(hWndTV, &tvI);
if(tvI.lParam)
{
LPTVITEM_STUFF lptvi = (LPTVITEM_STUFF) tvI.lParam;
if(lptvi)
{
// if(lptvi->ulObjectType==MAPI_DISTLIST) //only free this for groups
LocalFreeSBinary(lptvi->lpsbEID);
LocalFree(lptvi);
}
}
}
//$$////////////////////////////////////////////////////////////////////////////////////////
//
// ClearTreeViewItems - Clears the treeview of all its items
//
//////////////////////////////////////////////////////////////////////////////////////////
void FreeTreeNode(HWND hWndTV, HTREEITEM hItem)
{
HTREEITEM hTemp = NULL;
if(!hItem)
return;
FreeTVItemLParam(hWndTV, hItem);
hTemp = TreeView_GetChild(hWndTV, hItem);
while(hTemp)
{
FreeTreeNode(hWndTV, hTemp);
hTemp = TreeView_GetNextSibling(hWndTV, hTemp);
}
}
void ClearTreeViewItems(HWND hWndTV)
{
// Go through all the items and clear their lParams which we allocated earlier
HTREEITEM hRoot = TreeView_GetRoot(hWndTV);
while(hRoot)
{
FreeTreeNode(hWndTV, hRoot);
hRoot = TreeView_GetNextSibling(hWndTV, hRoot);
}
TreeView_DeleteAllItems(hWndTV);
}
//$$////////////////////////////////////////////////////////////////////////////////////////
//
// RemoveCurrentGroup - removes the currently selected group from the WAB
//
//////////////////////////////////////////////////////////////////////////////////////////
void RemoveCurrentGroup(LPBWI lpbwi, HWND hWnd, LPFILETIME lpftLast)
{
HRESULT hr = E_FAIL;
// Warn the user if they really want to do this ?
if(IDYES == ShowMessageBox( hWnd, idsRemoveGroupFromAB, MB_ICONEXCLAMATION | MB_YESNO ) )
{
LPSBinary lpsbEID = NULL;
// Get the entryid of this group
GetCurrentSelectionEID(lpbwi, bwi_hWndTV, &lpsbEID, NULL, FALSE);
if(lpsbEID)
{
HTREEITEM hItem = NULL;
// Delete the group contact from the WAB
hr = HrRemoveEntryFromWAB(bwi_lpIAB, lpsbEID->cb, (LPENTRYID)lpsbEID->lpb);
if(HR_FAILED(hr))
ShowMessageBox(hWnd, idsRemoveGroupError, MB_ICONEXCLAMATION | MB_OK);
// Remove selection from the current group
RemoveUpdateSelection(lpbwi);
// Update all
bwi_bDontRefreshLV = TRUE;
RefreshListView(lpbwi, lpftLast);
bwi_bDontRefreshLV = FALSE;
LocalFreeSBinary(lpsbEID);
}
}
}
//$$////////////////////////////////////////////////////////////////////////////////////////
//
// RemoveCurrentFolder - removes the currently selected folder and all its contents from the WAB
//
//////////////////////////////////////////////////////////////////////////////////////////
HRESULT RemoveCurrentFolder(LPBWI lpbwi, HWND hWnd, LPFILETIME lpftLast)
{
LPPTGDATA lpPTGData=GetThreadStoragePointer();
HRESULT hr = E_FAIL;
LPSPropValue lpPropArray = NULL;
SCODE sc;
ULONG i, j, cValues= 0;
SBinary sb = {0};
LPSBinary lpsbEID = NULL;
LPIAB lpIAB = bwi_lpIAB;
// Get the entryid of this folder
GetCurrentSelectionEID(lpbwi, bwi_hWndTV, &lpsbEID, NULL, FALSE);
if( !lpsbEID || !lpsbEID->cb || !lpsbEID->lpb || // can't delete root item
(lpIAB->lpWABCurrentUserFolder && (lpsbEID->cb==lpIAB->lpWABCurrentUserFolder->sbEID.cb) && //can't delete the current users folder
!memcmp(lpsbEID->lpb, lpIAB->lpWABCurrentUserFolder->sbEID.lpb, lpsbEID->cb) ) )
{
ShowMessageBox(hWnd, idsCannotDelete, MB_OK | MB_ICONEXCLAMATION);
goto out;
}
// ignore deletions to folders in non-profile mode ...
if(!bIsWABSessionProfileAware(bwi_lpIAB) || pt_bIsWABOpenExSession)
goto out;
// Warn the user if they really want to do this ?
if(IDYES == ShowMessageBox( hWnd, idsRemoveFolderFromAB, MB_ICONEXCLAMATION | MB_YESNO ) )
{
if(lpsbEID && lpsbEID->cb && lpsbEID->lpb) // can't delete root item
{
HTREEITEM hItem = NULL;
// Open the group and read its contents
if(!HR_FAILED(hr = ReadRecord( bwi_lpIAB->lpPropertyStore->hPropertyStore,
lpsbEID, 0, &cValues, &lpPropArray)))
{
for(i=0;i<cValues;i++)
{
if(lpPropArray[i].ulPropTag == PR_WAB_FOLDER_ENTRIES)
{
for(j=0;j<lpPropArray[i].Value.MVbin.cValues;j++)
{
hr = HrRemoveEntryFromWAB(bwi_lpIAB,
lpPropArray[i].Value.MVbin.lpbin[j].cb,
(LPENTRYID)lpPropArray[i].Value.MVbin.lpbin[j].lpb);
}
}
}
// Delete the group contact from the WAB
hr = DeleteRecord( bwi_lpIAB->lpPropertyStore->hPropertyStore, lpsbEID);
if(HR_FAILED(hr) && hr!=MAPI_E_INVALID_ENTRYID)
ShowMessageBox(hWnd, idsRemoveFolderError, MB_ICONEXCLAMATION | MB_OK);
// Remove selection from the current group
RemoveUpdateSelection(lpbwi);
// Update all
bwi_bDontRefreshLV = TRUE;
HrGetWABProfiles(bwi_lpIAB);
RefreshListView(lpbwi, lpftLast);
bwi_bDontRefreshLV = FALSE;
}
ReadRecordFreePropArray(NULL, cValues, &lpPropArray);
}
}
out:
LocalFreeSBinary(lpsbEID);
return hr;
}
//$$////////////////////////////////////////////////////////////////////////////////////////
//
// RemovesSelectedItems from the listview
//
// lpList is the ContentsList associated with the ListView which needs
// to be kept updated
//
//////////////////////////////////////////////////////////////////////////////////////////
void RemoveSelectedItemsFromListView(HWND hWndLV, LPRECIPIENT_INFO * lppList)
{
int iItemIndex = 0;
if(ListView_GetSelectedCount(hWndLV) <= 0)
goto exit;
SendMessage(hWndLV, WM_SETREDRAW, (WPARAM) FALSE, 0);
// Start removing from the bottom up
iItemIndex = ListView_GetNextItem(hWndLV, -1, LVNI_SELECTED);
while(iItemIndex != -1)
{
// Get the entryid of the selected item
LPRECIPIENT_INFO lpItem = GetItemFromLV(hWndLV, iItemIndex);
if(lpItem)
{
if(lpItem->lpNext)
lpItem->lpNext->lpPrev = lpItem->lpPrev;
if(lpItem->lpPrev)
lpItem->lpPrev->lpNext = lpItem->lpNext;
if(lppList && *lppList == lpItem)
*lppList = lpItem->lpNext;
FreeRecipItem(&lpItem);
}
ListView_DeleteItem(hWndLV, iItemIndex);
iItemIndex = ListView_GetNextItem(hWndLV, iItemIndex-1, LVNI_SELECTED);
}
SendMessage(hWndLV, WM_SETREDRAW, (WPARAM) TRUE, 0);
exit:
return;
}
//$$////////////////////////////////////////////////////////////////////////////////////////
//
// Removes selected items from the group and the WAB, if specified
//
//////////////////////////////////////////////////////////////////////////////////////////
void RemoveSelectedItemsFromCurrentGroup(LPBWI lpbwi, HWND hWnd, LPFILETIME lpftLast, BOOL bRemoveFromWAB)
{
// We want to remove the selected items from the current group and also
// remove them from the ListView ...
LPSBinary lpsbEID = NULL;
ULONG ulcValues = 0;
LPSPropValue lpPropArray = NULL;
HRESULT hr = S_OK;
LPMAILUSER lpMailUser = NULL;
ULONG ulObjType = 0;
ULONG i,j;
ULONG ulDLEntriesIndex = 0;
int id = (bRemoveFromWAB) ? idsRemoveSelectedFromGroupAndAB : idsRemoveSelectedFromGroup;
if( ListView_GetSelectedCount(bwi_hWndListAB) <= 0)
goto exit;
if(IDNO == ShowMessageBox(hWnd, id, MB_ICONEXCLAMATION | MB_YESNO))
goto exit;
GetCurrentSelectionEID(lpbwi, bwi_hWndTV, &lpsbEID, NULL, FALSE);
if(!lpsbEID)
goto exit;
if (HR_FAILED(hr = bwi_lpAdrBook->lpVtbl->OpenEntry(bwi_lpAdrBook,
lpsbEID->cb, // cbEntryID
(LPENTRYID)lpsbEID->lpb, // entryid
NULL, // interface
MAPI_MODIFY, // ulFlags
&ulObjType, // returned object type
(LPUNKNOWN *)&lpMailUser)))
{
// Failed! Hmmm.
DebugTraceResult( TEXT("Address: IAB->OpenEntry:"), hr);
goto exit;
}
Assert(lpMailUser);
if (HR_FAILED(hr = lpMailUser->lpVtbl->GetProps(lpMailUser,
NULL, // lpPropTagArray
MAPI_UNICODE, // ulFlags
&ulcValues, // how many properties were there?
&lpPropArray)))
{
DebugTraceResult( TEXT("Address: IAB->GetProps:"), hr);
goto exit;
}
// Scan these props for the PR_WAB_DL_ENTRIES
// We ignore PR_WAB_DL_ONEOFFS here because technically you can't have one-offs in the Browse view therefore
// should never need to delete OneOffs in this function
for(i=0;i<ulcValues;i++)
{
if(lpPropArray[i].ulPropTag == PR_WAB_DL_ENTRIES)
{
ulDLEntriesIndex = i;
break;
}
}
if(!ulDLEntriesIndex)
goto exit;
{
// cycle through the list view items entryids
int iItemIndex = ListView_GetNextItem(bwi_hWndListAB, -1, LVNI_SELECTED);
while(iItemIndex != -1)
{
// Get the entryid of the selected item
ULONG cbItemEID = 0;
LPENTRYID lpItemEID = NULL;
LPRECIPIENT_INFO lpItem = GetItemFromLV(bwi_hWndListAB, iItemIndex);
if(lpItem)
{
RemovePropFromMVBin(lpPropArray,
ulcValues,
ulDLEntriesIndex,
(LPVOID) lpItem->lpEntryID,
lpItem->cbEntryID);
if(bRemoveFromWAB)
{
// Delete the group contact from the WAB
// Note; This is very inefficient - we should ideally create a
// SBinaryArray and call deleteentries all at once
// We'll leave that for some later time <TBD> <BUGBUG>
hr = HrRemoveEntryFromWAB(bwi_lpIAB, lpItem->cbEntryID, lpItem->lpEntryID);
}
}
iItemIndex = ListView_GetNextItem(bwi_hWndListAB, iItemIndex, LVNI_SELECTED);
}
}
// Knock out the PR_WAB_DL_ENTRIES property so we can overwrite it
{
if (HR_FAILED(hr = lpMailUser->lpVtbl->DeleteProps(lpMailUser,
(LPSPropTagArray) &tagaDLEntriesProp,
NULL)))
{
DebugTraceResult( TEXT("IAB->DeleteProps:"), hr);
goto exit;
}
}
if (HR_FAILED(hr = lpMailUser->lpVtbl->SetProps(lpMailUser,
ulcValues,
lpPropArray,
NULL)))
{
DebugTraceResult( TEXT("Address: IAB->GetProps:"), hr);
goto exit;
}
if(HR_FAILED(hr = lpMailUser->lpVtbl->SaveChanges(lpMailUser, KEEP_OPEN_READONLY)))
{
DebugTraceResult( TEXT("SaveChanges failed: "), hr);
goto exit;
}
// update the file stamp
//if (lpftLast) {
// CheckChangedWAB(bwi_lpIAB->lpPropertyStore, lpftLast);
//}
bwi_bDeferNotification = TRUE;
RemoveSelectedItemsFromListView(bwi_hWndListAB, &bwi_lpContentsList);
exit:
if(lpsbEID)
LocalFreeSBinary(lpsbEID);
if(lpPropArray)
MAPIFreeBuffer(lpPropArray);
if(lpMailUser)
lpMailUser->lpVtbl->Release(lpMailUser);
return;
}
//$$////////////////////////////////////////////////////////////////////////////////////////
//
// Shows properties on the currently selected group or folder
//
//////////////////////////////////////////////////////////////////////////////////////////
void ViewCurrentGroupProperties(LPBWI lpbwi, LPFILETIME lpftLast)
{
LPSBinary lpsbEID = NULL;
HWND hWnd = GetParent(bwi_hWndTV);
ULONG ulObjectType = 0;
GetCurrentSelectionEID(lpbwi, bwi_hWndTV, &lpsbEID, &ulObjectType, FALSE);
if(lpsbEID && (ulObjectType==MAPI_DISTLIST))
{
bwi_lpAdrBook->lpVtbl->Details( bwi_lpAdrBook,
(PULONG_PTR) &hWnd,
NULL,
NULL,
lpsbEID->cb,
(LPENTRYID)lpsbEID->lpb,
NULL,
NULL,
NULL,
0);
// if the item name changed, update it
{
LPRECIPIENT_INFO lpInfo = NULL;
ReadSingleContentItem( bwi_lpAdrBook,
lpsbEID->cb,
(LPENTRYID) lpsbEID->lpb,
&lpInfo);
if(lpInfo)
{
TV_ITEM tvi = {0};
tvi.hItem = bwi_hti ? bwi_hti : TreeView_GetSelection(bwi_hWndTV);
tvi.mask = TVIF_HANDLE;
TreeView_GetItem(bwi_hWndTV, &tvi);
tvi.mask |= TVIF_TEXT;
tvi.pszText = lpInfo->szDisplayName;
tvi.cchTextMax = lstrlen(tvi.pszText)+1;
TreeView_SetItem(bwi_hWndTV, &tvi);
FreeRecipItem(&lpInfo);
}
}
UpdateListViewContents(lpbwi, lpsbEID, ulObjectType);
// Update the wab file write time so the timer doesn't
// catch this change and refresh.
//if (lpftLast) {
// CheckChangedWAB(bwi_lpIAB->lpPropertyStore, lpftLast);
//}
bwi_bDeferNotification = TRUE;
}
else if(lpsbEID //&& lpsbEID->cb && lpsbEID->lpb
&& (ulObjectType==MAPI_ABCONT)
&& bIsWABSessionProfileAware(bwi_lpIAB))
{
// view properties on the folder entry
if(!HR_FAILED(HrFolderProperties(GetParent(bwi_hWndTV), bwi_lpIAB, lpsbEID, NULL, NULL)))
{
//UpdateViewFoldersMenu(lpbwi, hWnd);
RefreshListView(lpbwi,lpftLast);
}
}
if(lpsbEID)
LocalFreeSBinary(lpsbEID);
return;
}
//$$////////////////////////////////////////////////////////////////////////////////////////
//
// Processes messages for the TREE view control
//
//////////////////////////////////////////////////////////////////////////////////////////
LRESULT ProcessTreeViewMessages(LPBWI lpbwi, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LPFILETIME lpftLast)
{
NM_TREEVIEW * pNm = (NM_TREEVIEW *)lParam;
switch(pNm->hdr.code)
{
case NM_SETFOCUS:
UpdateToolbarAndMenu(lpbwi);
break;
case TVN_KEYDOWN:
//UpdateToolbarAndMenu(lpbwi);
switch(((LV_KEYDOWN FAR *) lParam)->wVKey)
{
case VK_DELETE:
SendMessage (hWnd, WM_COMMAND, (WPARAM) IDM_FILE_DELETE, 0);
return 0;
break;
case VK_RETURN:
SendMessage (hWnd, WM_COMMAND, (WPARAM) IDM_FILE_PROPERTIES, 0);
return 0;
}
break;
case TVN_SELCHANGEDW:
case TVN_SELCHANGEDA:
{
if(!bwi_bDontRefreshLV)
UpdateLV(lpbwi);
UpdateToolbarAndMenu(lpbwi);
}
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
BOOL SplitterHitTest(HWND hWndT, LPARAM lParam)
{
LONG xPos = LOWORD(lParam);
LONG yPos = HIWORD(lParam);
RECT rc;
if(!IsWindowVisible(hWndT))
return FALSE;
GetChildClientRect(hWndT, &rc);
if( (xPos <= rc.right) && (xPos >= rc.left) &&
(yPos <= rc.bottom) && (yPos >= rc.top) )
return TRUE;
else
return FALSE;
}
/////////////////////////////////////////
// Stolen (essentially) from COMMCTRL
HBITMAP FAR PASCAL CreateDitherBitmap(COLORREF crFG, COLORREF crBG)
{
PBITMAPINFO pbmi;
HBITMAP hbm;
HDC hdc;
int i;
long patGray[8];
DWORD rgb;
pbmi = (PBITMAPINFO)LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER) + (sizeof(RGBQUAD) * 16));
if (!pbmi)
return NULL;
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth = 8;
pbmi->bmiHeader.biHeight = 8;
pbmi->bmiHeader.biPlanes = 1;
pbmi->bmiHeader.biBitCount = 1;
pbmi->bmiHeader.biCompression = BI_RGB;
rgb = crBG;
pbmi->bmiColors[0].rgbBlue = GetBValue(rgb);
pbmi->bmiColors[0].rgbGreen = GetGValue(rgb);
pbmi->bmiColors[0].rgbRed = GetRValue(rgb);
pbmi->bmiColors[0].rgbReserved = 0;
rgb = crFG;
pbmi->bmiColors[1].rgbBlue = GetBValue(rgb);
pbmi->bmiColors[1].rgbGreen = GetGValue(rgb);
pbmi->bmiColors[1].rgbRed = GetRValue(rgb);
pbmi->bmiColors[1].rgbReserved = 0;
/* initialize the brushes */
for (i = 0; i < 8; i++)
if (i & 1)
patGray[i] = 0xAAAA5555L; // 0x11114444L; // lighter gray
else
patGray[i] = 0x5555AAAAL; // 0x11114444L; // lighter gray
hdc = GetDC(NULL);
// REVIEW: We cast am array of long to (BYTE const *). Is it ok for Win32?
hbm = CreateDIBitmap(hdc, &pbmi->bmiHeader, CBM_INIT,
(BYTE const *)patGray, pbmi, DIB_RGB_COLORS);
ReleaseDC(NULL, hdc);
LocalFree(pbmi);
return hbm;
}
// Stolen (essentially) from COMMCTRL
HBRUSH FAR PASCAL CreateDitherBrush(COLORREF crFG, COLORREF crBG)
{
HBITMAP hbm;
HBRUSH hbrRet = NULL;
hbm = CreateDitherBitmap(crFG, crBG);
if (hbm)
{
hbrRet = CreatePatternBrush(hbm);
DeleteObject(hbm);
}
return(hbrRet);
}
//////////////////////////////////////////
// Stolen from Athena
void DragSplitterBar(LPBWI lpbwi, HWND hwnd, HWND hWndT, LPARAM lParam)
{
MSG msg;
int x, y, dx, dy;
RECT rcSplitter;
RECT rc;
HDC hdc;
LONG lStyle;
HBRUSH hbrDither, hbrOld;
int nAccel = 2;
lStyle = GetWindowLong(hwnd, GWL_STYLE);
SetWindowLong(hwnd, GWL_STYLE, (lStyle & ~WS_CLIPCHILDREN));
GetChildClientRect(hWndT, &rcSplitter);
//GetWindowRect(hWndT, &rcSplitter);
x = rcSplitter.left;
y = rcSplitter.top;
dx = rcSplitter.right - rcSplitter.left;
dy = rcSplitter.bottom - rcSplitter.top;
GetWindowRect(hwnd, &rc);
hdc = GetDC(hwnd);
hbrDither = CreateDitherBrush(RGB(255, 255, 255), RGB(0, 0, 0));
if (hbrDither)
hbrOld = (HBRUSH)SelectObject(hdc, (HGDIOBJ)hbrDither);
// split bar loop...
PatBlt(hdc, x, y, dx, dy, PATINVERT);
SetCapture(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
if ( msg.message == WM_LBUTTONUP ||
msg.message == WM_LBUTTONDOWN ||
msg.message == WM_RBUTTONDOWN)
break;
if (GetCapture() != hwnd)
{
msg.message = WM_RBUTTONDOWN; // treat as cancel
break;
}
if ( msg.message == WM_KEYDOWN ||
msg.message == WM_SYSKEYDOWN ||
(msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST) )
{
if (msg.message == WM_KEYDOWN)
{
nAccel = 4;
if (msg.wParam == VK_LEFT)
{
msg.message = WM_MOUSEMOVE;
msg.pt.x -= nAccel/2;
}
else if (msg.wParam == VK_RIGHT)
{
msg.message = WM_MOUSEMOVE;
msg.pt.x += nAccel/2;
}
else if ( msg.wParam == VK_RETURN ||
msg.wParam == VK_ESCAPE)
{
break;
}
if (msg.pt.x > rc.right)
msg.pt.x = rc.right;
if (msg.pt.x < rc.left)
msg.pt.x = rc.left;
SetCursorPos(msg.pt.x, msg.pt.y);
}
if (msg.message == WM_MOUSEMOVE)
{
int lo, hi;
if (msg.pt.x > rc.right)
msg.pt.x = rc.right;
if (msg.pt.x < rc.left)
msg.pt.x = rc.left;
ScreenToClient(hwnd, &msg.pt);
// Clip out the parts we don't want so
// that we do a single PatBlt (less
// flicker for small movements).
if (x < msg.pt.x)
{
lo = x;
hi = msg.pt.x;
}
else
{
lo = msg.pt.x;
hi = x;
}
if (hi < lo+dx)
{
ExcludeClipRect(hdc, hi, y, lo+dx, y+dy);
}
else
{
ExcludeClipRect(hdc, lo+dx, y, hi, y+dy);
}
// Erase the old and draw the new in one draw.
PatBlt(hdc, lo, y, hi-lo+dx, dy, PATINVERT);
SelectClipRgn(hdc, NULL);
x = msg.pt.x;
}
}
else
{
DispatchMessage(&msg);
}
}
ReleaseCapture();
// erase old
PatBlt(hdc, x, y, dx, dy, PATINVERT);
if (hbrDither)
{
if (hbrOld)
SelectObject(hdc, hbrOld);
DeleteObject(hbrDither);
}
ReleaseDC(hwnd, hdc);
SetWindowLong(hwnd, GWL_STYLE, lStyle);
if (msg.wParam != VK_ESCAPE && msg.message != WM_RBUTTONDOWN && msg.message != WM_CAPTURECHANGED)
{
RECT rcTV;
GetChildClientRect(bwi_hWndTV, &rcTV);
MoveWindow(bwi_hWndTV, rcTV.left, rcTV.top, x, rcTV.bottom - rcTV.top, TRUE);
ResizeAddressBookChildren(lpbwi, hwnd);
InvalidateRect( bwi_hWndSplitter,NULL,TRUE);
InvalidateRect( bwi_hWndEditQF,NULL,TRUE);
InvalidateRect( bwi_hWndStaticQF,NULL,TRUE);
InvalidateRect( hwnd,NULL,TRUE);
RedrawWindow( hwnd, NULL, NULL,
RDW_ERASE | RDW_INVALIDATE | RDW_ERASENOW | RDW_UPDATENOW );
RedrawWindow( bwi_hWndEditQF, NULL, NULL,
RDW_ERASE | RDW_INVALIDATE | RDW_ERASENOW | RDW_UPDATENOW );
}
return;
}
//$$//////////////////////////////////////////////////////////////////////////////
//
// Opens a VCard and adds it to the WAB and to the Current group
// szVCardFIle can be a NULL in which case we open the OpenFile dialog
//
//////////////////////////////////////////////////////////////////////////////////
HRESULT OpenAndAddVCard(LPBWI lpbwi, LPTSTR szVCardFile)
{
HRESULT hr = S_OK;
LPSPropValue lpProp = NULL;
hr = VCardImport(bwi_hWndAB, bwi_lpAdrBook, szVCardFile, &lpProp);
// if the above failed, then the lpProp will have nothing in it
// in cases where there are multiple nested vcards, the error could
// be from one vcard, but the rest may have imported .. if they
// imported successfully then lpProp will have something in it ..
// so use lpProp instead of hr ..
if(lpProp)
{
if(HR_FAILED(hr))
hr = MAPI_W_ERRORS_RETURNED;
bwi_bDontRefreshLV = TRUE;
if(lpProp && PROP_TYPE(lpProp->ulPropTag) == PT_MV_BINARY)
{
if(!bIsSelectedTVContainer(lpbwi))
{
LPSBinary lpsbEIDGroup = NULL;
ULONG ulObjectType = 0;
bwi_hti = NULL; // if this wasnt a context-initiated action, dont trust the hti setting
GetCurrentSelectionEID(lpbwi, bwi_hWndTV, &lpsbEIDGroup, &ulObjectType, FALSE);
if(lpsbEIDGroup)
{
ULONG i = 0;
for(i=0;i<lpProp->Value.MVbin.cValues;i++)
{
hr = AddEntryToContainer(bwi_lpAdrBook, ulObjectType,
lpsbEIDGroup->cb, (LPENTRYID) lpsbEIDGroup->lpb,
lpProp->Value.MVbin.lpbin[i].cb,
(LPENTRYID) lpProp->Value.MVbin.lpbin[i].lpb);
}
}
}
}
FreeBufferAndNull(&lpProp);
bwi_bDontRefreshLV = FALSE;
// if updated and showing PAB, refresh list
SendMessage(bwi_hWndAB, WM_COMMAND, (WPARAM) IDM_VIEW_REFRESH, 0);
}
return hr;
}
//$$
// Updates the switch-user's menu if this is not a wab.exe initiated call
//
//
void UpdateSwitchUsersMenu(HWND hWnd, LPIAB lpIAB)
{
if( memcmp(&lpIAB->guidPSExt, &MPSWab_GUID_V4, sizeof(GUID)) ||
!bIsThereACurrentUser(lpIAB) || !bAreWABAPIProfileAware(lpIAB))
{
HMENU hMenuMain = GetMenu(hWnd);
HMENU hMenuFile = GetSubMenu(hMenuMain,idmFile);
// Need to remove the print and the seperator
RemoveMenu(hMenuFile, idmFSep5, MF_BYPOSITION);
RemoveMenu(hMenuFile, idmAllContents, MF_BYPOSITION);
RemoveMenu(hMenuFile, idmSwitchUsers, MF_BYPOSITION);
DrawMenuBar(hWnd);
}
}
//$$
//
// Turns of the print menu if requested to do so
//
//
void UpdatePrintMenu(HWND hWnd)
{
if(!bPrintingOn)
{
HMENU hMenuMain = GetMenu(hWnd);
HMENU hMenuFile = GetSubMenu(hMenuMain,idmFile);
// Need to remove the print and the seperator
RemoveMenu(hMenuFile, idmFSep4, MF_BYPOSITION);
RemoveMenu(hMenuFile, idmPrint, MF_BYPOSITION);
DrawMenuBar(hWnd);
}
return;
}
/*
-
- UpdateViewFoldersMenu
-
*
*
*/
void UpdateViewFoldersMenu(LPBWI lpbwi, HWND hWnd)
{
#ifdef FUTURE
HMENU hMenuMain = GetMenu(hWnd);
HMENU hMenuFile = GetSubMenu(hMenuMain,idmFile);
HMENU hMenu = GetSubMenu(hMenuFile, idmFolders);
LPIAB lpIAB = bwi_lpIAB;
int i = 0;
// If profiles are not enabled or there are no subfolders, remove the folder option completely
if(!bDoesThisWABHaveAnyUsers(lpIAB))
{
// remove all folder options:
// Remove the Folders option from the View Menu
RemoveMenu(hMenuFile, idmSepFolders, MF_BYPOSITION);
RemoveMenu(hMenuFile, idmFolders, MF_BYPOSITION);
goto out;
}
else
{
// removing screws up numbering and svrewss up access to other folders
// so just disable
EnableMenuItem(hMenuFile, idmSepFolders, MF_BYPOSITION | (lpIAB->lpWABFolders ? MF_ENABLED : MF_GRAYED));
EnableMenuItem(hMenuFile, idmFolders, MF_BYPOSITION | (lpIAB->lpWABFolders ? MF_ENABLED : MF_GRAYED));
if(lpIAB->lpWABFolders)
AddFolderListToMenu(hMenu, lpIAB);
goto out;
}
// if there is only 1 folder in the wab and this is the shared folder
// then disable the folder item because there is nothing to be done
//if( !bIsThereACurrentUser(lpIAB) )
//{
// EnableMenuItem(hMenuView, idmFolders, MF_BYPOSITION | MF_GRAYED);
// goto out;
//}
out:
#endif // FUTURE
return;
}
//$$
// UpdateOutlookMenus
//
// Some menus are not accessible when running from outlook
//
// Tools | Options Menu should not be accessible from WAB when
// outlook is in Full MAPI mode because then Outlook doesnt use
// WAB and we dont want to give the option to the user of
// switching to the WAB
//
void UpdateOutlookMenus(HWND hWnd)
{
LPPTGDATA lpPTGData=GetThreadStoragePointer();
BOOL bNoOptions = TRUE;
HMENU hMenuMain = GetMenu(hWnd);
HMENU hMenuFile = NULL;
HMENU hMenu = NULL;
if( pt_bIsWABOpenExSession &&
lpfnAllocateBufferExternal && // **ASSUMPTION** that Outlook always
lpfnAllocateMoreExternal && lpfnFreeBufferExternal) // passes in memory allocators ..!!!
{
/*
hMenuFile = GetSubMenu(hMenuMain, idmFile);
{
// Need to remove the import AddressBook and Export Addressbook options
hMenu = GetSubMenu(hMenuFile, idmImport);
RemoveMenu(hMenu, IDM_TOOLS_IMPORT_OTHER, MF_BYCOMMAND);
hMenu = GetSubMenu(hMenuFile, idmExport);
RemoveMenu(hMenu, IDM_TOOLS_EXPORT_OTHER, MF_BYCOMMAND);
RemoveMenu(hMenu, IDM_TOOLS_EXPORT_WAB, MF_BYCOMMAND);
}
*/
/*
// [PaulHi] 12/18/98 Raid #62640
// Disable the Import/Export menu items before anything is removed and
// order gets messed up.
EnableMenuItem(hMenuFile, idmImport, MF_GRAYED | MF_BYPOSITION);
EnableMenuItem(hMenuFile, idmExport, MF_GRAYED | MF_BYPOSITION);
//Also remove New Folder menu
RemoveMenu(hMenuFile, IDM_FILE_NEWFOLDER, MF_BYCOMMAND);
*/
}
else
{
// Not called from Outlook ...
// check if Outlook is using the WAB .. if it isnt, we dont want
// to show the Tools Options menu
//
HKEY hKey = NULL;
LPTSTR lpReg = TEXT("Software\\Microsoft\\Office\\8.0\\Outlook\\Setup");
LPTSTR lpOMI = TEXT("MailSupport");
BOOL bUsingWAB = FALSE;
if(ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE, lpReg, 0, KEY_READ, &hKey))
{
DWORD dwType = 0, dwSize = sizeof(DWORD), dwData = 0;
if(ERROR_SUCCESS == RegQueryValueEx(hKey, lpOMI, NULL, &dwType, (LPBYTE)&dwData, &dwSize))
{
if(dwType == REG_DWORD && dwData == 0)
bUsingWAB = TRUE;
}
}
if(hKey)
RegCloseKey(hKey);
bNoOptions = !bUsingWAB;
}
// [PaulHi] 1/4/99 The pt_bIsWABOpenExSession variable is mis-named. This
// boolean used to be true only if the WAB was opened from WABOpenEx, i.e,
// by Outlook using the Outlook store. However, this boolean is now true in
// the case where the WAB is open from WABOpen but still uses the Outlook
// store because it is in "shared mode", i.e., the use outlook store registry
// setting is true.
if(pt_bIsWABOpenExSession)
{
//Also remove New Folder menu
hMenuFile = GetSubMenu(hMenuMain, idmFile);
// [PaulHi] 1/4/99 Raid #64016
// Disable the Import/Export menu items before anything is removed and
// order gets messed up.
// This is similar to Raid #62640 except we need to disable import/export
// WHENEVER the WAB is opened to use the Outlook store since it doesn't
// know how to import/export Outlook store information.
EnableMenuItem(hMenuFile, idmImport, MF_GRAYED | MF_BYPOSITION);
EnableMenuItem(hMenuFile, idmExport, MF_GRAYED | MF_BYPOSITION);
RemoveMenu(hMenuFile, IDM_FILE_NEWFOLDER, MF_BYCOMMAND);
// [PaulHi] 3/22/99 Raid 73457 Remove the Profile... Edit menu item
// since profiles are turned off when in Outlook mode
hMenu = GetSubMenu(hMenuMain, idmEdit);
RemoveMenu(hMenu, IDM_EDIT_SETME, MF_BYCOMMAND); // Profile... menu item
RemoveMenu(hMenu, 5, MF_BYPOSITION); // Seperator
}
if(bNoOptions)
{
// Hide the tools options option
//
hMenuFile = GetSubMenu(hMenuMain,idmTools);
// Need to remove the second-last and third-last items
RemoveMenu(hMenuFile, 3, MF_BYPOSITION); //Seperator
RemoveMenu(hMenuFile, 2, MF_BYPOSITION); //Options
DrawMenuBar(hWnd);
}
return;
}
void UpdateCustomColumnMenuText(HWND hWnd)
{
HMENU hMenuMain = GetMenu(hWnd);
HMENU hMenuView = GetSubMenu(hMenuMain, idmView);
int nDiff = idmViewMax - GetMenuItemCount(hMenuView); // in case stuff was deleted off this menu
HMENU hMenu = GetSubMenu(hMenuView, idmSortBy - nDiff);
MENUITEMINFO mii = {0};
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_TYPE;
mii.fType = MFT_STRING;
if(PR_WAB_CUSTOMPROP1 && lstrlen(szCustomProp1))
{
mii.dwTypeData = (LPTSTR) szCustomProp1;
mii.cch = lstrlen(szCustomProp1) + 1;
SetMenuItemInfo(hMenu, 3, TRUE, &mii);
}
if(PR_WAB_CUSTOMPROP2 && lstrlen(szCustomProp2))
{
mii.dwTypeData = (LPVOID) szCustomProp2;
mii.cch = lstrlen(szCustomProp2) + 1;
SetMenuItemInfo(hMenu, 2, TRUE, &mii);
}
DrawMenuBar(hWnd);
return;
}
//$$
// bCheckForOutlook
// Checks if the Outlook Contact Store is available
//
// If this is an outlook session, this is true by default
// Otherwise hunt for presence of outlwab.dll
//
BOOL bCheckForOutlook()
{
LPPTGDATA lpPTGData=GetThreadStoragePointer();
if(pt_bIsWABOpenExSession)
return TRUE;
// Not an outlook session ..
// Look for OutlWAB.Dll
return bCheckForOutlookWABDll(NULL, 0);
}
//$$
//
// Dialog proc for the options dialog
//
/*//$$************************************************************************
//
// fnSearch - Search Dialog Proc
//
**************************************************************************/
INT_PTR CALLBACK fnOptionsDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
{
if(!bCheckForOutlook()) //<TBD> - No Outlook 98 is installed
{
// Disable the Outlook option
EnableWindow(GetDlgItem(hDlg, IDC_OPTIONS_RADIO_OUTLOOK), FALSE);
SendMessage(hDlg, WM_COMMAND, (WPARAM) MAKEWPARAM(IDC_OPTIONS_RADIO_WAB, BN_CLICKED), (LPARAM) GetDlgItem(hDlg, IDC_OPTIONS_RADIO_WAB));
if(bUseOutlookStore()) // make sure reg says false .. not true
SetRegistryUseOutlook(FALSE);
}
else
{
// Correct type of Outlook is installed
int id = bUseOutlookStore() ? IDC_OPTIONS_RADIO_OUTLOOK : IDC_OPTIONS_RADIO_WAB;
SendMessage(hDlg, WM_COMMAND,
(WPARAM) MAKEWPARAM(id, BN_CLICKED),
(LPARAM) GetDlgItem(hDlg, id));
}
}
// [PaulHi] Be sure to set the child window fonts
EnumChildWindows(hDlg, SetChildDefaultGUIFont, (LPARAM)PARENT_IS_DIALOG);
return TRUE;
break;
case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
// Check which option button is checked
{
BOOL bOriginal = bUseOutlookStore();
BOOL bCurrent = IsDlgButtonChecked(hDlg, IDC_OPTIONS_RADIO_OUTLOOK);
SetRegistryUseOutlook(bCurrent);
if(bCurrent != bOriginal)
ShowMessageBox(hDlg, idsStoreChangeOnRestart, MB_ICONINFORMATION | MB_OK);
}
// fall thru
case IDCANCEL:
EndDialog(hDlg, 0);
break;
case IDC_OPTIONS_RADIO_WAB:
CheckRadioButton(hDlg,
IDC_OPTIONS_RADIO_OUTLOOK,
IDC_OPTIONS_RADIO_WAB,
IDC_OPTIONS_RADIO_WAB);
break;
case IDC_OPTIONS_RADIO_OUTLOOK:
CheckRadioButton(hDlg,
IDC_OPTIONS_RADIO_OUTLOOK,
IDC_OPTIONS_RADIO_WAB,
IDC_OPTIONS_RADIO_OUTLOOK);
break;
}
break;
}
return FALSE;
}
//$$
//
// Shows the options dialog
//
void HrShowOptionsDlg(HWND hWndParent)
{
BOOL bChange = FALSE;
INT_PTR nRetVal = DialogBoxParam( hinstMapiX, MAKEINTRESOURCE(IDD_DIALOG_OPTIONS),
hWndParent, fnOptionsDlgProc, (LPARAM) &bChange);
}
//$$////////////////////////////////////////////////////////////////////////////
//
// AddTVItem
//
// Adds an item to the Tree View - item can be folder/container or group
//
////////////////////////////////////////////////////////////////////////////////
HTREEITEM AddTVItem(HWND hWndTV, LPTSTR lpszName, HTREEITEM hParentItem, HTREEITEM htiAfter,
LPSBinary lpsbParentEID, LPSBinary lpEID, ULONG ulObjectType)
{
TV_ITEM tvI = {0};
TV_INSERTSTRUCT tvIns = {0};
LPTVITEM_STUFF lptvStuff = NULL;
HTREEITEM htiRet = NULL;
int img = 0;
if(ulObjectType == MAPI_DISTLIST)
img = imageDistList;
else
{
if(!lpEID || !lpEID->cb || !lpEID->lpb)
img = imageAddressBook;
else
img = imageFolderClosed;
}
tvI.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
tvI.iImage = img;
tvI.iSelectedImage = (img == imageFolderClosed) ? imageFolderOpen : img;
tvI.pszText = lpszName;
tvI.cchTextMax = lstrlen(tvI.pszText);
lptvStuff = LocalAlloc(LMEM_ZEROINIT, sizeof(TVITEM_STUFF));
if(!lptvStuff)
goto out;
lptvStuff->ulObjectType = ulObjectType;
if(lpEID)
{
LPSBinary lpsbEID = NULL;
lpsbEID = LocalAlloc(LMEM_ZEROINIT, sizeof(SBinary));
if(lpsbEID)
{
if(lpEID->cb)
SetSBinary(lpsbEID, lpEID->cb, lpEID->lpb);
lptvStuff->lpsbEID = lpsbEID;
}
}
lptvStuff->lpsbParent = lpsbParentEID;
lptvStuff->hItemParent = hParentItem;
tvI.lParam = (LPARAM) lptvStuff;
tvIns.item = tvI;
tvIns.hInsertAfter = htiAfter;
tvIns.hParent = hParentItem;
htiRet = TreeView_InsertItem(hWndTV, &tvIns);
/* Uncomment this to make the top level folders show up in bold
if(htiRet && !hParentItem)
{
TVITEM tvi = {0};
tvi.mask = TVIF_STATE;
tvi.state = tvi.stateMask = TVIS_BOLD;
tvi.hItem = htiRet;
TreeView_SetItem(hWndTV, &tvi);
}*/
out:
return htiRet;
}
//$$///////////////////////////////////////////////////////////////////////////
//
// AddTVFolderGroup
//
// Add a group under a contact folder in the TV
//
///////////////////////////////////////////////////////////////////////////////
HTREEITEM AddTVFolderGroup(LPBWI lpbwi, HWND hWndTV, HTREEITEM hParentItem, LPSBinary lpsbParentEID, LPSBinary lpsbEID)
{
TCHAR szBufName[MAX_UI_STR];
if(!lpsbEID || !lpsbEID->cb || !lpsbEID->lpb)
return NULL;
// Get the name of this group
if(HR_FAILED(FillListFromGroup( bwi_lpAdrBook,
lpsbEID->cb, (LPENTRYID) lpsbEID->lpb,
szBufName, ARRAYSIZE(szBufName), NULL)))
return NULL;
return AddTVItem( hWndTV, szBufName,
hParentItem, TVI_SORT,
lpsbParentEID, lpsbEID,
MAPI_DISTLIST);
}
//$$///////////////////////////////////////////////////////////////////////////////
//
// FillTreeView
//
// Fill the TreeView with Contact Folders and groups as appropriate
//
// lpsbSelection - entryid of item to select after filling
//
///////////////////////////////////////////////////////////////////////////////////
void FillTreeView(LPBWI lpbwi, HWND hWndTV, LPSBinary lpsbSelection)
{
// Way to do this
//
// If this is the WAB, just add an AddressBook item to the top of the list
// otherwise if this is Outlook, get a list of all the contact folders and
// add them to the Root of the TV.
//
// Then go through the list of contact folders and for each one, add the groups
// at the next level
// We cache the TVITEM_STUFF info on each item, contact folder or group
//
HTREEITEM hItem = NULL;
LPPTGDATA lpPTGData=GetThreadStoragePointer();
LPIAB lpIAB = bwi_lpIAB;
int nDepth = 0;
bwi_bDontRefreshLV = TRUE;
SendMessage(hWndTV, WM_SETREDRAW, (WPARAM) FALSE, 0);
ClearTreeViewItems(hWndTV);
EnterCriticalSection(&lpIAB->cs);
// Check if this is an outlook session
if( pt_bIsWABOpenExSession || bIsWABSessionProfileAware(lpIAB) )
{
ULONG iolkci, colkci;
OlkContInfo *rgolkci;
HTREEITEM htiTopLevel = NULL;
colkci = pt_bIsWABOpenExSession ? lpIAB->lpPropertyStore->colkci : lpIAB->cwabci;
Assert(colkci);
rgolkci = pt_bIsWABOpenExSession ? lpIAB->lpPropertyStore->rgolkci : lpIAB->rgwabci;
Assert(rgolkci);
// Add the multiple folders here
// Since each folder is added under the first item, we start last first
// to preserve the folder order.
if(pt_bIsWABOpenExSession)
{
do
{
iolkci = colkci-1;
htiTopLevel = AddTVItem( hWndTV, rgolkci[iolkci].lpszName, NULL, TVI_FIRST, NULL,
(iolkci==0/*&& pt_bIsWABOpenExSession*/) ? NULL : rgolkci[iolkci].lpEntryID,
MAPI_ABCONT);
colkci--;
} while(colkci!=0);
}
else
{
// WAB Profiles ..
// We want to add the first item ( TEXT("All Contacts")) at the top and all user folders
// at the same level and all ordinary folders under the user level folders
LPWABFOLDER lpFolder = (bIsThereACurrentUser(lpIAB) ? lpIAB->lpWABCurrentUserFolder : lpIAB->lpWABUserFolders);
// With a given user, we only add that users folder
// Without a given user we add everyones folders
// if there are no user folders at all then we don't have user's configured and
// all folders should show up at the top level
if(!lpFolder)
lpFolder = lpIAB->lpWABFolders;
while(lpFolder)
{
LPWABFOLDERLIST lpFolderList = lpFolder->lpFolderList;
htiTopLevel = AddTVItem(hWndTV, lpFolder->lpFolderName, NULL, TVI_SORT, NULL, &lpFolder->sbEID, MAPI_ABCONT);
while(lpFolderList)
{
// Don't show Shared Folders under the user-folders .. shared folders will be
// shown under the PAB folder
if(!lpFolderList->lpFolder->bShared)
AddTVItem(hWndTV, lpFolderList->lpFolder->lpFolderName, htiTopLevel, TVI_SORT, NULL, &lpFolderList->lpFolder->sbEID, MAPI_ABCONT);
lpFolderList = lpFolderList->lpNext;
}
TreeView_Expand(hWndTV, htiTopLevel, TVE_EXPAND);
if(lpIAB->lpWABCurrentUserFolder)
break;
lpFolder=lpFolder->lpNext;
}
// Add the Virtual PAB item to the top of the list so we can sort the others
htiTopLevel = AddTVItem(hWndTV, rgolkci[0].lpszName, NULL, TVI_FIRST, NULL, rgolkci[0].lpEntryID, MAPI_ABCONT);
// add all the SHARED folders under the root item
lpFolder = lpIAB->lpWABFolders;
while(lpFolder)
{
if(lpFolder->bShared)
AddTVItem(hWndTV, lpFolder->lpFolderName, htiTopLevel, TVI_SORT, NULL, &lpFolder->sbEID, MAPI_ABCONT);
lpFolder=lpFolder->lpNext;
}
//if(!bIsThereACurrentUser(lpIAB) && !bDoesThisWABHaveAnyUsers(lpIAB))
TreeView_Expand(hWndTV, htiTopLevel, TVE_EXPAND);
}
}
else
{
TCHAR sz[MAX_PATH];
*sz = '\0';
LoadString(hinstMapiX, idsContacts/*IDS_ADDRBK_CAPTION*/, sz, ARRAYSIZE(sz));
AddTVItem( hWndTV, sz, NULL, TVI_FIRST, NULL, NULL, MAPI_ABCONT);
}
//TreeView_SortChildren(hWndTV, NULL, 0);
// Now we have all the contact folders at the root level ..
// we can now add the groups under each folder
hItem = TreeView_GetRoot(hWndTV);
//if(bDoesThisWABHaveAnyUsers(lpIAB)) // don't populate any groups under the Root Item if Users exist
// hItem = TreeView_GetNextSibling(hWndTV, hItem);
while(hItem)
{
TV_ITEM tvI = {0};
// Find all the Groups in this folder
tvI.mask = TVIF_PARAM | TVIF_HANDLE;
tvI.hItem = hItem;
if(TreeView_GetItem(hWndTV, &tvI))
{
if(tvI.lParam && ((LPTVITEM_STUFF)tvI.lParam)->ulObjectType==MAPI_ABCONT)
{
LPTVITEM_STUFF lptvStuff = (LPTVITEM_STUFF) tvI.lParam;
SPropertyRestriction PropRes = {0};
SPropValue sp = {0};
HRESULT hr = S_OK;
ULONG ulCount = 0;
LPSBinary rgsbEntryIDs = NULL;
sp.ulPropTag = PR_OBJECT_TYPE;
sp.Value.l = MAPI_DISTLIST;
PropRes.ulPropTag = PR_OBJECT_TYPE;
PropRes.relop = RELOP_EQ;
PropRes.lpProp = &sp;
if(!HR_FAILED(hr = FindRecords( lpIAB->lpPropertyStore->hPropertyStore,
lptvStuff->lpsbEID, 0, TRUE, &PropRes,
&ulCount,&rgsbEntryIDs)))
{
ULONG i;
for(i=0;i<ulCount;i++)
AddTVFolderGroup(lpbwi, hWndTV, hItem, lptvStuff->lpsbEID, &(rgsbEntryIDs[i]));
FreeEntryIDs(lpIAB->lpPropertyStore->hPropertyStore, ulCount, rgsbEntryIDs);
}
}
}
TreeView_SortChildren(hWndTV, hItem, 0);
// Start at the top level, look for children,
// if no children, look for next sibling,
// if no sibling, look for parent's sibling
{
HTREEITEM hTemp = NULL;
if(nDepth < 1) // Assumes we only have 2 levels of folders - this way we don't look at the third level which may only have groups
hTemp = TreeView_GetChild(hWndTV, hItem);
if(hTemp)
nDepth++;
else
hTemp = TreeView_GetNextSibling(hWndTV, hItem);
if(!hTemp)
{
if(hTemp = TreeView_GetParent(hWndTV, hItem))
{
nDepth--;
hTemp = TreeView_GetNextSibling(hWndTV, hTemp);
}
}
hItem = hTemp;
}
}
if(!lpsbSelection && bIsThereACurrentUser(bwi_lpIAB))
lpsbSelection = &bwi_lpIAB->lpWABCurrentUserFolder->sbEID;
UpdateTVGroupSelection(hWndTV, lpsbSelection);
//if(!lpsbSelection || !lpsbSelection->cb || !lpsbSelection->lpb)
{
LPSBinary lpsb = NULL;
//UpdateListViewContents(lpbwi, &sb, MAPI_ABCONT);
ULONG ulObjectType;
GetCurrentSelectionEID(lpbwi, bwi_hWndTV, &lpsb, &ulObjectType, FALSE);
UpdateListViewContents(lpbwi, lpsb, ulObjectType);
LocalFreeSBinary(lpsb);
}
SendMessage(hWndTV, WM_SETREDRAW, (WPARAM) TRUE, 0);
bwi_bDontRefreshLV = FALSE;
LeaveCriticalSection(&lpIAB->cs);
{
// if there is only a single item in the tree view, remove the haslines style
// as it looks pretty strange..
//
DWORD dwStyle = GetWindowLong(hWndTV, GWL_STYLE);
int nCount = TreeView_GetCount(hWndTV);
if(nCount > 1)
dwStyle |= TVS_HASLINES;
else
dwStyle &= ~TVS_HASLINES;
SetWindowLong(hWndTV, GWL_STYLE, dwStyle);
}
return;
}
typedef struct _FolderInfo
{
BOOL bIsReadOnly; // Sets DLG ctrls to readonly
BOOL bIsShared; // Indicates if shared
BOOL bForceShared; // Indicates that shared-checkbox should be shared and non-modifiable
LPTSTR lpsz; // Folder name (in and out param)
LPTSTR lpszOldName; // Old name so we can track name changes
LPTSTR lpszOwnerName; // Person who created this folder
LPIAB lpIAB;
LPSBinary lpsbEID; // EID of the folder
LPWABFOLDER lpParentFolder; // Parent folder this folder will be associated with
SBinary sbNew; // returned new EID of new folder
} FINFO, * LPFINFO;
//$$
/*
- fnFolderDlgProc
-
* Dialog proc for the Folder dialog
*
*/
INT_PTR CALLBACK fnFolderDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
{
LPFINFO lpfi = (LPFINFO) lParam;
LPTSTR lpsz = lpfi->lpsz;
HWND hWndCheck = GetDlgItem(hDlg, IDC_FOLDER_CHECK_SHARE);
SetWindowLongPtr(hDlg,DWLP_USER,(LPARAM) lpfi); //Save this for future reference
SendMessage(GetDlgItem(hDlg,IDC_FOLDER_EDIT_NAME), EM_SETLIMITTEXT,(WPARAM) MAX_UI_STR-1,0);
if(lpsz && lstrlen(lpsz))
SetDlgItemText(hDlg, IDC_FOLDER_EDIT_NAME, lpsz);
CheckDlgButton(hDlg, IDC_FOLDER_CHECK_SHARE, (lpfi->bIsShared ? BST_CHECKED : BST_UNCHECKED));
if(lpfi->lpszOwnerName)
{
TCHAR sz[MAX_PATH];
TCHAR szTmp[MAX_PATH], *lpszTmp;
*sz = '\0';
GetDlgItemText(hDlg, IDC_FOLDER_STATIC_CREATEDBY, sz, CharSizeOf(sz));
if(sz && lstrlen(sz))
{
LPTSTR lpsz = NULL;
CopyTruncate(szTmp, lpfi->lpszOwnerName, MAX_PATH - 1);
lpszTmp = szTmp;
if(FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING |FORMAT_MESSAGE_ARGUMENT_ARRAY,
sz, 0, 0, (LPTSTR) &lpsz, 0, (va_list *)&lpszTmp))
{
SetDlgItemText(hDlg, IDC_FOLDER_STATIC_CREATEDBY, lpsz);
LocalFree(lpsz);
ShowWindow(GetDlgItem(hDlg, IDC_FOLDER_STATIC_CREATEDBY), SW_SHOWNORMAL);
}
}
}
if(lpfi->bIsReadOnly)
{
SendDlgItemMessage(hDlg, IDC_FOLDER_EDIT_NAME, EM_SETREADONLY, (WPARAM) TRUE, 0);
EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
EnableWindow(hWndCheck, FALSE);
SendMessage(hDlg, DM_SETDEFID, IDCANCEL, 0);
SetFocus(GetDlgItem(hDlg,IDCANCEL));
}
else
SetFocus(GetDlgItem(hDlg,IDC_FOLDER_EDIT_NAME));
if(lpfi->bForceShared)
{
CheckDlgButton(hDlg, IDC_FOLDER_CHECK_SHARE, BST_CHECKED);
EnableWindow(hWndCheck, FALSE);
}
if(!bDoesThisWABHaveAnyUsers(lpfi->lpIAB))
{
// there are no users configured so hide the sharing option
EnableWindow(hWndCheck, FALSE);
ShowWindow(hWndCheck, SW_HIDE);
}
}
break;
case WM_COMMAND:
switch(GET_WM_COMMAND_CMD(wParam,lParam)) //check the notification code
{
case EN_CHANGE:
switch(LOWORD(wParam))
{ //update title as necessary
case IDC_FOLDER_EDIT_NAME:
{
TCHAR szBuf[MAX_UI_STR];
if(GetWindowText((HWND) lParam,szBuf,CharSizeOf(szBuf)))
SetWindowPropertiesTitle(hDlg, szBuf);
}
break;
}
break;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
// Check that text is filled in
{
TCHAR sz[MAX_UI_STR];
GetDlgItemText(hDlg, IDC_FOLDER_EDIT_NAME, sz, CharSizeOf(sz));
if(!lstrlen(sz))
{
ShowMessageBox(hDlg, idsAddFolderName, MB_ICONINFORMATION | MB_OK);
return FALSE;
}
else
{
LPFINFO lpfi = (LPFINFO) GetWindowLongPtr(hDlg,DWLP_USER);
LPTSTR lpsz = lpfi->lpsz;
HRESULT hr = S_OK;
BOOL bShared = IsDlgButtonChecked(hDlg, IDC_FOLDER_CHECK_SHARE);
if(lpfi->lpsbEID && sz) //existing entry
{
ULONG ulFlags = 0;
// Did the name change or sharing info changed
if(lstrcmp(sz, lpfi->lpszOldName)!=0)
ulFlags |= FOLDER_UPDATE_NAME;
if(lpfi->bIsShared!=bShared)
ulFlags |= FOLDER_UPDATE_SHARE;
if(ulFlags)
{
if(!HR_FAILED(hr = HrUpdateFolderInfo(lpfi->lpIAB, lpfi->lpsbEID, ulFlags, bShared, sz)))
{
//reload the profiles so that this is updated
HrGetWABProfiles(lpfi->lpIAB);
}
}
}
else
{
// if we're here we have a valid folder name ..
hr = HrCreateNewFolder( lpfi->lpIAB, sz,
lstrlen(lpfi->lpIAB->szProfileID)?lpfi->lpIAB->szProfileID:NULL,
FALSE, lpfi->lpParentFolder, bShared, &lpfi->sbNew);
}
if(HR_FAILED(hr))
{
if(hr == MAPI_E_COLLISION)
ShowMessageBox(hDlg, idsEntryAlreadyInWAB, MB_ICONINFORMATION | MB_OK);
else
ShowMessageBox(hDlg, idsCouldNotSelectUser, MB_ICONEXCLAMATION | MB_OK);
return FALSE;
}
}
}
EndDialog(hDlg, IDOK);
break;
case IDCANCEL:
EndDialog(hDlg, IDCANCEL);
break;
}
break;
}
return FALSE;
}
/*
- HrFolderProperties
-
* if FolderEID is NULL,
* Creates a newfolder, adds it to the current profile, updates the UI
* in TreeView and in the View | Folders menu ...
* else opens properties on the folder so user can change the name
* if desired
*
* lpsbEID - NULL if creating a new folder else EID of folder to view
* lpParentFolder - User folder under which this is being created
* lpsbnew - return EID of newly created folder
*/
HRESULT HrFolderProperties(HWND hWndParent, LPIAB lpIAB, LPSBinary lpsbEID,
LPWABFOLDER lpParentFolder, LPSBinary lpsbNew)
{
HRESULT hr = S_OK;
int nRetVal;
TCHAR sz[MAX_UI_STR];
LPTSTR lpsz = NULL;
FINFO fi = {0};
fi.lpszOwnerName = NULL;
*sz = '\0';
if(lpsbEID)
{
LPWABFOLDER lpFolder = FindWABFolder(lpIAB, lpsbEID, NULL, NULL);
if( (!lpsbEID->cb && !lpsbEID->lpb) )
fi.bIsShared = TRUE;
if( (!lpsbEID->cb && !lpsbEID->lpb) ||
(lpFolder && lpFolder->lpProfileID && lstrlen(lpFolder->lpProfileID)) )
fi.bIsReadOnly = TRUE;
if(lpFolder)
{
StrCpyN(sz, lpFolder->lpFolderName, ARRAYSIZE(sz));
fi.lpszOldName = lpFolder->lpFolderName;
fi.bIsShared = lpFolder->bShared;
fi.lpszOwnerName = lpFolder->lpFolderOwner;
}
else
{
LoadString(hinstMapiX, idsSharedContacts/*idsAllContacts*/, sz, ARRAYSIZE(sz));
}
}
else
{
// this is a new folder ..
// if it doesn't have a parent and userfolders are already configured then it's being created
// in the shared folders in which case we should force the shared-folder option
if(bDoesThisWABHaveAnyUsers(lpIAB) && !lpParentFolder)
fi.bForceShared = TRUE;
}
fi.lpsz = sz;
fi.lpIAB = lpIAB;
fi.lpsbEID = lpsbEID;
fi.lpParentFolder = lpParentFolder;
nRetVal = (int) DialogBoxParam( hinstMapiX, MAKEINTRESOURCE(IDD_DIALOG_FOLDER),
hWndParent, fnFolderDlgProc, (LPARAM) &fi);
if(nRetVal == IDCANCEL)
{
hr = MAPI_E_USER_CANCEL;
goto out;
}
if(lpsbNew)
SetSBinary(lpsbNew, fi.sbNew.cb, fi.sbNew.lpb);
out:
LocalFreeAndNull((LPVOID *) (&fi.sbNew.lpb));
return hr;
}
/*
- UpdateLV
-
* Refreshes the list view based on the current selection
*
*/
void UpdateLV(LPBWI lpbwi)
{
ULONG ulObjectType = 0;
LPSBinary lpsbEID = NULL;
bwi_hti = NULL;
GetCurrentSelectionEID(lpbwi, bwi_hWndTV, &lpsbEID, &ulObjectType, FALSE);
UpdateListViewContents(lpbwi, lpsbEID, ulObjectType);
LocalFreeSBinary(lpsbEID);
bwi_bDeferNotification = TRUE;
}
#ifdef COLSEL_MENU
/**
This function will update the listview and write the selected custom column selections out
to the registry.
*/
BOOL UpdateOptionalColumns( LPBWI lpbwi, ULONG iColumn )
{
LVCOLUMN lvCol = {0};
HKEY hKey = NULL;
LPTSTR lpszColTitle = (iColumn == colHomePhone ) ? szCustomProp1 : szCustomProp2;
ULONG ulProp = (iColumn == colHomePhone ) ? PR_WAB_CUSTOMPROP1 : PR_WAB_CUSTOMPROP2;
DWORD cbProp = 0;
LPIAB lpIAB = bwi_lpIAB;
HKEY hKeyRoot = (lpIAB && lpIAB->hKeyCurrentUser) ? lpIAB->hKeyCurrentUser : HKEY_CURRENT_USER;
DWORD dwDisposition = 0;
BOOL fRet = FALSE;
TCHAR szBuf[MAX_PATH];
if( iColumn != colHomePhone && iColumn != colOfficePhone )
goto exit;
LoadString(hinstMapiX, lprgAddrBookColHeaderIDs[iColumn], szBuf, ARRAYSIZE(szBuf));
lvCol.mask = LVCF_TEXT;
lvCol.pszText = (lpszColTitle && lstrlen(lpszColTitle))? lpszColTitle : szBuf;
if( !ListView_SetColumn( bwi_hWndListAB, iColumn, &lvCol ) )
{
DebugTrace( TEXT("could not setcolumntext: %x\n"), GetLastError() );
goto exit;
}
if(ulProp)
{
// begin registry stuff
if (ERROR_SUCCESS != RegCreateKeyEx(hKeyRoot, lpNewWABRegKey, 0, //reserved
NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
NULL, &hKey, &dwDisposition))
{
goto exit;
}
cbProp = sizeof( ULONG );
if(ERROR_SUCCESS != RegSetValueEx( hKey,
(iColumn == colHomePhone ? szPropTag1 : szPropTag2),
0, REG_DWORD, (LPBYTE)&ulProp, cbProp))
goto exit;
}
fRet = TRUE;
exit:
if(hKey)
RegCloseKey(hKey);
return fRet;
}
#endif // COLSEL_MENU
/*
- HrExportWAB
-
* Supposed to export data out of the .WAB into another .wab file.
* Ideally, user should be able to specify an existing WAB file and TEXT("push") data
* into that file from this file.
* Instead, we do a cheesy implementation here where we let the user specify a file name to
* create and we then just copy the current .WAB file to the new file name
*
* Obviously this method doesn't work when WAB is sharing the Outlook store and in that
* case we remove this option from the Menu
*
*/
extern BOOL PromptForWABFile(HWND hWnd, LPTSTR szFile, DWORD cchSizeFile, BOOL bOpen);
HRESULT HrExportWAB(HWND hWnd, LPBWI lpbwi)
{
HRESULT hr = E_FAIL;
TCHAR szFile[MAX_PATH];
HCURSOR hOldC = NULL;
if (!PromptForWABFile(hWnd, szFile, ARRAYSIZE(szFile), FALSE))
{
hr = MAPI_E_USER_CANCEL;
goto out;
}
//Check if file already exists ..
if(0xFFFFFFFF != GetFileAttributes(szFile))
{
// Ask user if they want to overwrite
if(IDNO == ShowMessageBoxParam(hWnd,
IDE_VCARD_EXPORT_FILE_EXISTS,
MB_ICONEXCLAMATION | MB_YESNO | MB_SETFOREGROUND,
szFile))
{
hr = MAPI_E_USER_CANCEL;
goto out;
}
}
hOldC = SetCursor(LoadCursor(NULL, IDC_WAIT));
// Still here, means go ahead and copy the current .wab file to the new place ...
if(!CopyFile(GetWABFileName(bwi_lpIAB->lpPropertyStore->hPropertyStore,FALSE), szFile, FALSE))
{
DebugTrace( TEXT("WAB File export failed: %d\n"), GetLastError());
goto out;
}
if(hOldC)
{
SetCursor(hOldC);
hOldC = NULL;
}
ShowMessageBoxParam(hWnd, idsWABExportSuccess, MB_OK | MB_ICONEXCLAMATION, szFile);
hr = S_OK;
out:
if(HR_FAILED(hr) && hr!=MAPI_E_USER_CANCEL)
ShowMessageBox(hWnd, idsExportError, MB_OK | MB_ICONEXCLAMATION);
if(hOldC)
SetCursor(hOldC);
return hr;
}
void DestroyImageLists(LPBWI lpbwi)
{
HIMAGELIST hImageList;
if (NULL == gpfnImageList_Destroy)
return;
if (IsWindow(bwi_hWndTools))
{
// Destroy Image Lists created in ui_clbar.cpp's InitToolbar()
hImageList = (HIMAGELIST) SendMessage(bwi_hWndTools, TB_GETIMAGELIST, 0, 0);
if (NULL != hImageList)
gpfnImageList_Destroy(hImageList);
hImageList = (HIMAGELIST) SendMessage(bwi_hWndTools, TB_GETHOTIMAGELIST, 0, 0);
if (NULL != hImageList)
gpfnImageList_Destroy(hImageList);
hImageList = (HIMAGELIST) SendMessage(bwi_hWndTools, TB_GETDISABLEDIMAGELIST, 0, 0);
if (NULL != hImageList)
gpfnImageList_Destroy(hImageList);
}
if (IsWindow(bwi_hWndTV))
{
// Destroy Image Lists created in ui_abook.c's InitChildren()
hImageList = TreeView_GetImageList (bwi_hWndTV, TVSIL_NORMAL);
if (NULL != hImageList)
gpfnImageList_Destroy(hImageList);
}
}