//////////////////////////////////////////////////////////////////////////////////////// // // // 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 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) ? // 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;indexiedefault"), 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;ilpCreateParams; 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 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;ilpWABCurrentUserFolder->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;jlpNext = *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;ilpPropertyStore->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;ilpEntryID, 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 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;iValue.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()) // - 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;ilpsbEID, &(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); } }