///////////////////////////////////////////////////////////////////////////// // Copyright (C) 1993-1996 Microsoft Corporation. All Rights Reserved. // // MODULE: menuutil.cpp // // PURPOSE: Reusable menu & menu command handling code // #include "pch.hxx" #include "resource.h" #include "menuutil.h" #include "imnact.h" #include "strconst.h" #include "fldrprop.h" #include "mailutil.h" #include "mimeutil.h" #include "inetcfg.h" #include "newfldr.h" #include "browser.h" #include "instance.h" #include "statbar.h" #include "storutil.h" #include "subscr.h" #include "demand.h" #include "menures.h" #include "statnery.h" #include "store.h" #include #include #include #include "acctutil.h" static const UINT c_rgidNewsNoShow[] = { ID_NEW_FOLDER, ID_RENAME, ID_DELETE_FOLDER, SEP_MAILFOLDER }; static const UINT c_rgidSubNoShow[] = { ID_SUBSCRIBE, ID_UNSUBSCRIBE, SEP_SUBSCRIBE }; static const UINT c_rgidSyncNoShow[] = { ID_POPUP_SYNCHRONIZE, SEP_SYNCHRONIZE }; static const UINT c_rgidCatchUpNoShow[] = { ID_CATCH_UP, SEP_CATCH_UP }; void DeleteMenuItems(HMENU hMenu, const UINT *rgid, UINT cid) { Assert(rgid != NULL); Assert(cid != 0); for ( ; cid > 0; cid--, rgid++) DeleteMenu(hMenu, *rgid, MF_BYCOMMAND); } // // FUNCTION: MenuUtil_GetContextMenu() // // PURPOSE: Returns a handle to the context menu that is appropriate for // the folder type passed in pidl. The correct menu items will // be enabled, disabled, bolded, etc. // // PARAMETERS: // pidl - PIDL that points to the folder that the caller needs a // context menu for. // phMenu - Returns the handle to a popup menu. // // RETURN VALUE: // S_OK - phMenu contains a valid hMenu for the folder // E_UNEXPECTED - Either there was a problem loading the menu or the // folder type was unrecognized. // E_FAIL - The folder type doesn't support a menu. // HRESULT MenuUtil_GetContextMenu(FOLDERID idFolder, IOleCommandTarget *pTarget, HMENU *phMenu) { HRESULT hr; TCHAR sz[CCHMAX_STRINGRES]; FOLDERINFO Folder; HMENU hMenu; int idMenu; // Get folder INfo hr = g_pStore->GetFolderInfo(idFolder, &Folder); if (FAILED(hr)) return hr; // Root ? if (FOLDERID_ROOT == idFolder || ISFLAGSET(Folder.dwFlags, FOLDER_SERVER)) idMenu = IDR_SERVER_POPUP; else idMenu = IDR_FOLDER_POPUP; if (0 == (hMenu = LoadPopupMenu(idMenu))) { g_pStore->FreeRecord(&Folder); return (E_OUTOFMEMORY); } // Bold the default menu items MENUITEMINFO mii; if (!(MF_GRAYED & GetMenuState(hMenu, ID_OPEN_FOLDER, MF_BYCOMMAND))) { mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_STATE; mii.fState = MFS_DEFAULT; SetMenuItemInfo(hMenu, ID_OPEN_FOLDER, FALSE, &mii); } if (idMenu == IDR_SERVER_POPUP) { if (Folder.tyFolder != FOLDER_IMAP) DeleteMenu(hMenu, ID_IMAP_FOLDERS, MF_BYCOMMAND); if (Folder.tyFolder != FOLDER_NEWS) DeleteMenu(hMenu, ID_NEWSGROUPS, MF_BYCOMMAND); } else { if (Folder.tyFolder == FOLDER_IMAP) { AthLoadString(idsShowFolderCmd, sz, ARRAYSIZE(sz)); ModifyMenu(hMenu, ID_SUBSCRIBE, MF_BYCOMMAND | MF_STRING, ID_SUBSCRIBE, sz); AthLoadString(idsHideFolderCmd, sz, ARRAYSIZE(sz)); ModifyMenu(hMenu, ID_UNSUBSCRIBE, MF_BYCOMMAND | MF_STRING, ID_UNSUBSCRIBE, sz); } if (FOLDER_DELETED != Folder.tySpecial) DeleteMenu(hMenu, ID_EMPTY_WASTEBASKET, MF_BYCOMMAND); if (FOLDER_JUNK != Folder.tySpecial) DeleteMenu(hMenu, ID_EMPTY_JUNKMAIL, MF_BYCOMMAND); if (Folder.tyFolder == FOLDER_NEWS) DeleteMenuItems(hMenu, c_rgidNewsNoShow, ARRAYSIZE(c_rgidNewsNoShow)); if (Folder.tyFolder != FOLDER_NEWS && Folder.tyFolder != FOLDER_IMAP) DeleteMenuItems(hMenu, c_rgidSubNoShow, ARRAYSIZE(c_rgidSubNoShow)); if (Folder.tyFolder == FOLDER_LOCAL) DeleteMenuItems(hMenu, c_rgidSyncNoShow, ARRAYSIZE(c_rgidSyncNoShow)); if (Folder.tyFolder != FOLDER_NEWS) DeleteMenuItems(hMenu, c_rgidCatchUpNoShow, ARRAYSIZE(c_rgidCatchUpNoShow)); } // Enable / disable MenuUtil_EnablePopupMenu(hMenu, pTarget); // Return *phMenu = hMenu; g_pStore->FreeRecord(&Folder); return (S_OK); } void MenuUtil_OnSubscribeGroups(HWND hwnd, FOLDERID *pidFolder, DWORD cFolder, BOOL fSubscribe) { CStoreCB *pCB; HRESULT hr; DWORD iFolder; char szRes[CCHMAX_STRINGRES], szBuf[CCHMAX_STRINGRES]; FOLDERINFO info; Assert(hwnd != NULL); Assert(pidFolder != NULL); Assert(cFolder > 0); ZeroMemory(&info, sizeof(FOLDERINFO)); pCB = NULL; for (iFolder = 0; iFolder < cFolder; iFolder++, pidFolder++) { hr = g_pStore->GetFolderInfo(*pidFolder, &info); if (FAILED(hr)) break; if (iFolder == 0) { if (!fSubscribe) { if (cFolder == 1) { AthLoadString(info.tyFolder == FOLDER_NEWS ? idsWantToUnSubscribe : idsWantToHideFolder, szRes, ARRAYSIZE(szRes)); wnsprintf(szBuf, ARRAYSIZE(szBuf), szRes, info.pszName); } else { AthLoadString(info.tyFolder == FOLDER_NEWS ? idsWantToUnSubscribeN : idsWantToHideFolderN, szBuf, ARRAYSIZE(szBuf)); } if (IDOK != DoDontShowMeAgainDlg(hwnd, info.tyFolder == FOLDER_NEWS ? c_szRegUnsubscribe : c_szRegHide, MAKEINTRESOURCE(idsAthena), szBuf, MB_OKCANCEL)) { break; } } if (info.tyFolder == FOLDER_IMAP) { pCB = new CStoreCB; if (pCB == NULL) break; hr = pCB->Initialize(hwnd, fSubscribe ? MAKEINTRESOURCE(idsShowingFolders) : MAKEINTRESOURCE(idsHidingFolders), FALSE); if (FAILED(hr)) break; } } if (info.tySpecial == FOLDER_NOTSPECIAL && ISFLAGSET(info.dwFlags, FOLDER_SUBSCRIBED) ^ fSubscribe) { if (pCB != NULL) pCB->Reset(); hr = g_pStore->SubscribeToFolder(*pidFolder, fSubscribe, (IStoreCallback *)pCB); if (hr == E_PENDING) { Assert(info.tyFolder == FOLDER_IMAP); Assert(pCB != NULL); hr = pCB->Block(); } if (FAILED(hr)) break; } g_pStore->FreeRecord(&info); } g_pStore->FreeRecord(&info); if (pCB != NULL) { pCB->Close(); pCB->Release(); } } void MenuUtil_DeleteFolders(HWND hwnd, FOLDERID *pidFolder, DWORD cFolder, BOOL fNoTrash) { CStoreCB *pCB; HRESULT hr; DWORD iFolder, dwFlags; FOLDERID idDeleted, idServer; char szRes[CCHMAX_STRINGRES], szBuf[CCHMAX_STRINGRES], szFolder[CCHMAX_FOLDER_NAME]; FOLDERID *pidFolderT; FOLDERINFO info; BOOL fPermDelete, fCallback; Assert(hwnd != NULL); Assert(pidFolder != NULL); Assert(cFolder > 0); pCB = NULL; fCallback = FALSE; *szFolder = 0; if (fNoTrash) { dwFlags = DELETE_FOLDER_RECURSIVE | DELETE_FOLDER_NOTRASHCAN; fPermDelete = TRUE; } else { dwFlags = DELETE_FOLDER_RECURSIVE; fPermDelete = FALSE; for (iFolder = 0, pidFolderT = pidFolder; iFolder < cFolder; iFolder++, pidFolderT++) { hr = g_pStore->GetFolderInfo(*pidFolderT, &info); if (FAILED(hr)) return; // Skip deletion of any special folders if (info.tySpecial == FOLDER_NOTSPECIAL) { if (iFolder == 0 && cFolder == 1) StrCpyN(szFolder, info.pszName, ARRAYSIZE(szFolder)); if (info.tyFolder == FOLDER_IMAP || info.tyFolder == FOLDER_HTTPMAIL) { fPermDelete = TRUE; fCallback = TRUE; } else if (S_OK == IsParentDeletedItems(*pidFolderT, &idDeleted, &idServer)) { fPermDelete = TRUE; } } g_pStore->FreeRecord(&info); if (fPermDelete) break; } } if (fPermDelete) { if (cFolder == 1 && *szFolder != 0) { AthLoadString(idsWarnDeleteFolder, szRes, ARRAYSIZE(szRes)); wnsprintf(szBuf, ARRAYSIZE(szBuf), szRes, szFolder); } else { AthLoadString(idsWarnDeleteFolderN, szBuf, ARRAYSIZE(szBuf)); } } else { if (cFolder == 1 && *szFolder != 0) { AthLoadString(idsPromptDeleteFolder, szRes, ARRAYSIZE(szRes)); wnsprintf(szBuf, ARRAYSIZE(szBuf), szRes, szFolder); } else { AthLoadString(idsPromptDeleteFolderN, szBuf, ARRAYSIZE(szBuf)); } } if (IDYES != AthMessageBox(hwnd, MAKEINTRESOURCE(idsAthena), szBuf, 0, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2)) return; if (fCallback) { pCB = new CStoreCB; if (pCB == NULL) return; hr = pCB->Initialize(hwnd, MAKEINTRESOURCE(idsDeletingFolder), FALSE); if (FAILED(hr)) { pCB->Release(); return; } } for (iFolder = 0, pidFolderT = pidFolder; iFolder < cFolder; iFolder++, pidFolderT++) { hr = g_pStore->GetFolderInfo(*pidFolderT, &info); if (FAILED(hr)) break; // Skip deletion of any special folders if (info.tySpecial == FOLDER_NOTSPECIAL) { if (pCB != NULL) pCB->Reset(); hr = g_pStore->DeleteFolder(*pidFolderT, dwFlags, (IStoreCallback *)pCB); if (hr == E_PENDING) { Assert(info.tyFolder == FOLDER_IMAP || info.tyFolder == FOLDER_HTTPMAIL); Assert(pCB != NULL); hr = pCB->Block(); } } g_pStore->FreeRecord(&info); if (FAILED(hr)) break; } if (pCB != NULL) { pCB->Close(); pCB->Release(); } } void MenuUtil_SyncThisNow(HWND hwnd, FOLDERID idFolder) { UPDATENEWSGROUPINFO uni; HRESULT hr; DWORD dwFlags; FOLDERINFO info; char szAcctId[CCHMAX_ACCOUNT_NAME]; BOOL fNews, fMarked; if (g_pSpooler) { hr = g_pStore->GetFolderInfo(idFolder, &info); if (SUCCEEDED(hr)) { Assert(info.tyFolder == FOLDER_NEWS || info.tyFolder == FOLDER_IMAP || info.tyFolder == FOLDER_HTTPMAIL); if((info.tyFolder == FOLDER_NEWS) || (!g_pConMan->IsAccountDisabled((LPSTR)info.pszAccountId))) { fNews = (info.tyFolder == FOLDER_NEWS); dwFlags = fNews ? DELIVER_NEWS_TYPE : DELIVER_IMAP_TYPE; //Tells the spooler that this is a sync operation and not Send&Receive dwFlags |= DELIVER_OFFLINE_SYNC | DELIVER_WATCH | DELIVER_NOSKIP; if (!!(info.dwFlags & FOLDER_SERVER)) { // TODO: review these flags to make sure they are correct //dwFlags |= DELIVER_POLL | DELIVER_NEWS_SEND | DELIVER_NEWSIMAP_NOSKIP | DELIVER_NEWSIMAP_OFFLINE; dwFlags |= DELIVER_POLL | DELIVER_SEND | DELIVER_OFFLINE_FLAGS; g_pSpooler->StartDelivery(hwnd, info.pszAccountId, FOLDERID_INVALID, dwFlags); } else { hr = GetFolderAccountId(&info, szAcctId, ARRAYSIZE(szAcctId)); if (SUCCEEDED(hr)) { hr = HasMarkedMsgs(idFolder, &fMarked); if (SUCCEEDED(hr)) { uni.fNews = fNews; uni.dwGroupFlags = info.dwFlags; uni.cMarked = fMarked; uni.idCmd = dwFlags; // Display the dialog to find what get thing to get DialogBoxParam(g_hLocRes, MAKEINTRESOURCE(iddUpdateNewsgroup), hwnd, UpdateNewsgroup, (LPARAM)&uni); // Check to see if the user canceled if (uni.idCmd != -1) g_pSpooler->StartDelivery(hwnd, szAcctId, idFolder, uni.idCmd); } } } } g_pStore->FreeRecord(&info); } } } // // FUNCTION: MenuUtil_OnDelete() // // PURPOSE: Deletes the folder designated by the pidl. // // PARAMETERS: // hwnd - Handle of the window to display UI over // pidl - PIDL of the folder to browse to // pStore - Pointer to the store to delete folders from // void MenuUtil_OnDelete(HWND hwnd, FOLDERID idFolder, BOOL fNoTrash) { TCHAR szRes[CCHMAX_STRINGRES], szBuf[CCHMAX_STRINGRES]; FOLDERINFO Folder; IImnAccount *pAcct; // Get Folder Info if (FAILED(g_pStore->GetFolderInfo(idFolder, &Folder))) return; // Is a server if (ISFLAGSET(Folder.dwFlags, FOLDER_SERVER)) { Assert(g_pAcctMan); if (SUCCEEDED(g_pAcctMan->FindAccount(AP_ACCOUNT_ID, Folder.pszAccountId, &pAcct))) { AthLoadString(idsWarnDeleteAccount, szRes, ARRAYSIZE(szRes)); wnsprintf(szBuf, ARRAYSIZE(szBuf), szRes, Folder.pszName); if (IDYES == AthMessageBox(hwnd, MAKEINTRESOURCE(idsAthena), szBuf, 0, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2)) { pAcct->Delete(); } pAcct->Release(); } } else { if (Folder.tyFolder == FOLDER_NEWS) { MenuUtil_OnSubscribeGroups(hwnd, &idFolder, 1, FALSE); } else { MenuUtil_DeleteFolders(hwnd, &idFolder, 1, fNoTrash); } } g_pStore->FreeRecord(&Folder); } // // FUNCTION: MenuUtil_OnProperties() // // PURPOSE: Displays properties for the folder designated by the pidl // // PARAMETERS: // hwnd - Handle of the window to parent the properties // pidl - PIDL of the folder to browse to // void MenuUtil_OnProperties(HWND hwnd, FOLDERID idFolder) { IImnAccount *pAcct; FOLDERINFO Folder; if (SUCCEEDED(g_pStore->GetFolderInfo(idFolder, &Folder))) { if (ISFLAGSET(Folder.dwFlags, FOLDER_SERVER)) { if (SUCCEEDED(g_pAcctMan->FindAccount(AP_ACCOUNT_ID, Folder.pszAccountId, &pAcct))) { HRESULT hr; Assert(pAcct != NULL); DWORD dwFlags = ACCTDLG_SHOWIMAPSPECIAL | ACCTDLG_INTERNETCONNECTION | ACCTDLG_OE; if((DwGetOption(OPT_REVOKE_CHECK) != 0) && !g_pConMan->IsGlobalOffline()) dwFlags |= ACCTDLG_REVOCATION; //We want to use the new dialog for the properties, hence the new flag internetconnection hr = pAcct->ShowProperties(hwnd, dwFlags); if (S_OK == hr) // User hit "OK" to exit, not "Cancel" CheckIMAPDirty(Folder.pszAccountId, hwnd, idFolder, NOFLAGS); pAcct->Release(); } } else if (FOLDER_NEWS == Folder.tyFolder) { GroupProp_Create(hwnd, idFolder); } else { FolderProp_Create(hwnd, idFolder); } g_pStore->FreeRecord(&Folder); } } void MenuUtil_OnSetDefaultServer(FOLDERID idFolder) { TCHAR *sz; IImnAccount *pAcct = 0; FOLDERINFO Folder; if (FAILED(g_pStore->GetFolderInfo(idFolder, &Folder))) return; Assert(ISFLAGSET(Folder.dwFlags, FOLDER_SERVER)); if (SUCCEEDED(g_pAcctMan->FindAccount(AP_ACCOUNT_ID, Folder.pszAccountId, &pAcct))) { pAcct->SetAsDefault(); pAcct->Release(); } g_pStore->FreeRecord(&Folder); } void MenuUtil_OnMarkNewsgroups(HWND hwnd, int id, FOLDERID idFolder) { FOLDERINFO Folder; if (FAILED(g_pStore->GetFolderInfo(idFolder, &Folder))) return; Folder.dwFlags &= ~(FOLDER_DOWNLOADHEADERS | FOLDER_DOWNLOADNEW | FOLDER_DOWNLOADALL); if (id == ID_MARK_RETRIEVE_FLD_NEW_HDRS) Folder.dwFlags |= FOLDER_DOWNLOADHEADERS; else if (id == ID_MARK_RETRIEVE_FLD_ALL_MSGS) Folder.dwFlags |= FOLDER_DOWNLOADALL; else if (id == ID_MARK_RETRIEVE_FLD_NEW_MSGS) Folder.dwFlags |= FOLDER_DOWNLOADNEW; g_pStore->UpdateRecord(&Folder); g_pStore->FreeRecord(&Folder); } // BUG #41686 Catchup Implementation void MenuUtil_OnCatchUp(FOLDERID idFolder) { FOLDERINFO Folder; BOOL fFreeRange; CRangeList *pRange; IMessageFolder *pFolder; ADJUSTFLAGS flags; HCURSOR hcur; hcur = SetCursor(LoadCursor(NULL, IDC_WAIT)); if (SUCCEEDED(g_pStore->OpenFolder(idFolder, NULL, NOFLAGS, &pFolder))) { flags.dwAdd = ARF_READ; flags.dwRemove = ARF_DOWNLOAD; pFolder->SetMessageFlags(NULL, &flags, NULL, NULL); pFolder->Release(); } if (SUCCEEDED(g_pStore->GetFolderInfo(idFolder, &Folder))) { fFreeRange = FALSE; if (Folder.dwServerHigh > 0) { Folder.dwClientHigh = Folder.dwServerHigh; pRange = new CRangeList; if (pRange != NULL) { if (Folder.Requested.cbSize > 0) pRange->Load(Folder.Requested.pBlobData, Folder.Requested.cbSize); pRange->AddRange(0, Folder.dwServerHigh); fFreeRange = pRange->Save(&Folder.Requested.pBlobData, &Folder.Requested.cbSize); pRange->Release(); } } else { Folder.dwServerLow = 0; Folder.dwServerHigh = 0; Folder.dwServerCount = 0; } Folder.dwNotDownloaded = 0; g_pStore->UpdateRecord(&Folder); if (fFreeRange) MemFree(Folder.Requested.pBlobData); g_pStore->FreeRecord(&Folder); } SetCursor(hcur); } UINT GetMenuItemPos(HMENU hmenu, UINT cmd) { MENUITEMINFO mii; UINT cItem, ipos; cItem = GetMenuItemCount(hmenu); mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_ID; for (ipos = 0; ipos < cItem; ipos++) { SideAssert(GetMenuItemInfo(hmenu, ipos, TRUE, &mii)); if (mii.wID == cmd) break; } Assert(ipos != cItem); return(ipos); } BOOL MergeMenus(HMENU hmenuSrc, HMENU hmenuDst, int iPos, UINT uFlags) { MENUITEMINFO mii; UINT uState, i, cMerge; int cItem; BOOL fSepPre, fSepPost, fPopup, fCommand; BYTE rgch[CCHMAX_STRINGRES]; HMENU hmenuPopup; cMerge = GetMenuItemCount(hmenuSrc); if (cMerge == 0) return(TRUE); cItem = GetMenuItemCount(hmenuDst); if (iPos == MMPOS_REPLACE) { // destroy all menus while (RemoveMenu(hmenuDst, 0, MF_BYPOSITION)); cItem = 0; iPos = 0; } if (iPos == MMPOS_APPEND) iPos = cItem; fCommand = ((uFlags & MMF_BYCOMMAND) != 0); if (fCommand) iPos = GetMenuItemPos(hmenuDst, (UINT)iPos); if (iPos > cItem) iPos = cItem; fSepPre = FALSE; fSepPost = FALSE; if (uFlags & MMF_SEPARATOR) { if (iPos == 0) { // prepending, so stick in a separator after all the items // ASSUMES: never a separator as the last item in a menu if (cItem > 0) fSepPost = TRUE; } else if (iPos == cItem) { // appending, so stick in a separator before all the items // ASSUMES: never a separator as the first item in a menu fSepPre = TRUE; } else { // merging stuff into the middle of the menu, so need to check before and after uState = GetMenuState(hmenuDst, iPos - 1, MF_BYPOSITION); if (!(uState & MF_SEPARATOR)) fSepPre = TRUE; uState = GetMenuState(hmenuDst, iPos, MF_BYPOSITION); if (!(uState & MF_SEPARATOR)) fSepPost = TRUE; } } if (fSepPre) { InsertMenu(hmenuDst, (UINT)iPos, MF_SEPARATOR | MF_BYPOSITION, 0, NULL); iPos++; } ZeroMemory(&mii, sizeof(mii)); mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_ID | MIIM_STATE | MIIM_SUBMENU | MIIM_TYPE; for (i = 0; i < cMerge; i++) { mii.dwTypeData = (LPSTR)rgch; mii.cch = sizeof(rgch); mii.fType = 0; GetMenuItemInfo(hmenuSrc, i, TRUE, &mii); fPopup = (mii.hSubMenu != NULL); if (!fPopup && (mii.fType & MFT_SEPARATOR)) { InsertMenuItem(hmenuDst, (UINT)iPos, TRUE, &mii); } else { if (fPopup) { // its a popup submenu item hmenuPopup = CreateMenu(); MergeMenus(mii.hSubMenu, hmenuPopup, 0, 0); mii.hSubMenu = hmenuPopup; } InsertMenuItem(hmenuDst, (UINT)iPos, TRUE, &mii); } iPos++; } if (fSepPost) { InsertMenu(hmenuDst, (UINT)iPos, MF_SEPARATOR | MF_BYPOSITION, 0, NULL); iPos++; } return(TRUE); } // // REVIEW: We need this function because current version of USER.EXE does // not support pop-up only menu. // HMENU LoadPopupMenu(UINT id) { HMENU hmenuParent = LoadMenu(g_hLocRes, MAKEINTRESOURCE(id)); if (hmenuParent) { HMENU hpopup = GetSubMenu(hmenuParent, 0); RemoveMenu(hmenuParent, 0, MF_BYPOSITION); DestroyMenu(hmenuParent); return hpopup; } return NULL; } // walks a menu recursively, calling pfn for each item that isn't a separator void WalkMenu(HMENU hMenu, WALKMENUFN pfn, LPVOID lpv) { MENUITEMINFO mii; int i, cItems; ZeroMemory(&mii, sizeof(mii)); mii.cbSize = sizeof(mii); mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_SUBMENU; cItems = GetMenuItemCount(hMenu); for (i=0; iQueryStatus(&CMDSETID_OutlookExpress, cCmds, rgCmds, NULL))) { mii.cbSize = sizeof(MENUITEMINFO); // Now loop through the menu and apply the state for (i = 0; i < (int) cCmds; i++) { // The default thing we're going to update is the state mii.fMask = MIIM_STATE; // Enabled or Disabled if (rgCmds[i].cmdf & OLECMDF_ENABLED) mii.fState = MFS_ENABLED; else mii.fState = MFS_GRAYED; // Checked? if (rgCmds[i].cmdf & OLECMDF_LATCHED) mii.fState |= MFS_CHECKED; // Set the item state BOOL f; f = SetMenuItemInfo(hPopup, rgCmds[i].cmdID, FALSE, &mii); // Radio Check? if ((rgCmds[i].cmdf & OLECMDF_NINCHED) && rgCmds[i].cmdID != (-1)) { CheckMenuRadioItem(hPopup, rgCmds[i].cmdID, rgCmds[i].cmdID, rgCmds[i].cmdID, MF_BYCOMMAND); // mii.fMask |= MIIM_TYPE; // mii.fType = MFT_RADIOCHECK; // mii.fState |= MFS_CHECKED; } // Assert(f); } } SafeMemFree(rgCmds); return (hr); } void HandleMenuSelect(CStatusBar *pStatus, WPARAM wParam, LPARAM lParam) { UINT fuFlags, uItem; HMENU hmenu = GET_WM_MENUSELECT_HMENU(wParam, lParam); if (!pStatus) return; uItem = (UINT) LOWORD(wParam); fuFlags = (UINT) HIWORD(wParam); if (fuFlags & MF_POPUP) { MENUITEMINFO mii = { sizeof(MENUITEMINFO), MIIM_ID, 0 }; if (hmenu && IsMenu(hmenu)) { // Windows 98 seems to pass the command ID for popup items instead // of the documented position. So, if uItem is less than 40000 then // we can assume this is a menu position otherwise we assume it's // a command ID. if (GetMenuItemInfo(hmenu, uItem, (uItem < ID_FIRST), &mii)) { // change the parameters to simulate a normal menu item uItem = mii.wID; fuFlags = 0; } } } if (0 == (fuFlags & (MF_SYSMENU | MF_POPUP))) { TCHAR szMenu[256], szRes[CCHMAX_STRINGRES], szTemp[CCHMAX_STRINGRES + 256]; if (uItem >= ID_SORT_MENU_FIRST && uItem <= ID_SORT_MENU_LAST) { MENUITEMINFO mii = {0}; *szMenu = '\0'; *szRes = '\0'; *szTemp = '\0'; // must be a sort menu command! pull the menu name from the menu mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_TYPE; mii.dwTypeData = (LPSTR)szMenu; mii.cch = ARRAYSIZE(szMenu); if (GetMenuItemInfo((HMENU)lParam, uItem, FALSE, &mii)) { AthLoadString(idsSortMenuHelpControl, szRes, sizeof(szRes)); wnsprintf(szTemp, ARRAYSIZE(szTemp), szRes, szMenu); pStatus->ShowSimpleText(szTemp); } } else if (uItem >= ID_FIRST && uItem <= ID_LAST) { uItem = uItem - ID_FIRST; pStatus->ShowSimpleText(MAKEINTRESOURCE(uItem)); } else if ((uItem >= ID_VIEW_FILTER_FIRST) && (uItem <= ID_VIEW_FILTER_LAST)) { if ((uItem >= ID_VIEW_CURRENT) && (uItem <= ID_VIEW_RECENT_4)) { MENUITEMINFO mii = {0}; *szMenu = '\0'; *szRes = '\0'; *szTemp = '\0'; // must be a sort menu command! pull the menu name from the menu mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_TYPE; mii.dwTypeData = (LPSTR)szMenu; mii.cch = ARRAYSIZE(szMenu); if (GetMenuItemInfo((HMENU)lParam, uItem, FALSE, &mii)) { AthLoadString(idsViewMenuHelpControl, szRes, sizeof(szRes)); wnsprintf(szTemp, ARRAYSIZE(szTemp), szRes, szMenu); pStatus->ShowSimpleText(szTemp); } } else { uItem = uItem - ID_FIRST; pStatus->ShowSimpleText(MAKEINTRESOURCE(uItem)); } } else if ((uItem >= ID_MESSENGER_FIRST) && (uItem<= ID_MESSENGER_LAST)) { TCHAR szBuf[CCHMAX_STRINGRES] = ""; AthLoadString(uItem - ID_FIRST, szBuf, ARRAYSIZE(szBuf)); MenuUtil_BuildMessengerString(szBuf, ARRAYSIZE(szBuf)); pStatus->ShowSimpleText(szBuf); } else { if (uItem >= ID_ACCOUNT_FIRST && uItem <= ID_ACCOUNT_LAST) pStatus->ShowSimpleText(MAKEINTRESOURCE(idsSRAccountMenuHelp)); else pStatus->ShowSimpleText(0); } } else if (fuFlags == 0xffff && ((HMENU)lParam) == NULL) { pStatus->HideSimpleText(); } } // // FUNCTION: MenuUtil_SetPopupDefault() // // PURPOSE: Bolds the default item in a context menu // // PARAMETERS: // // RETURN VALUE: // void MenuUtil_SetPopupDefault(HMENU hPopup, UINT idDefault) { MENUITEMINFO mii; mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_STATE; if (GetMenuItemInfo(hPopup, idDefault, FALSE, &mii)) { mii.fState |= MFS_DEFAULT; SetMenuItemInfo(hPopup, idDefault, FALSE , &mii); } } // // FUNCTION: MenuUtil_ReplaceHelpMenu // // PURPOSE: Populates the ID_POPUP_HELP menu // void MenuUtil_ReplaceHelpMenu(HMENU hMenu) { MENUITEMINFO mii; if (mii.hSubMenu = LoadPopupMenu(IDR_HELP_POPUP)) { mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_SUBMENU; SetMenuItemInfo(hMenu, ID_POPUP_HELP, FALSE, &mii); } } // // FUNCTION: MenuUtil_ReplaceNewMsgMenu // // PURPOSE: Populates the ID_POPUP_HELP menu // void MenuUtil_ReplaceNewMsgMenus(HMENU hMenu) { MENUITEMINFO mii; if (mii.hSubMenu = LoadPopupMenu(IDR_NEW_MSG_POPUP)) { mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_SUBMENU; SetMenuItemInfo(hMenu, ID_POPUP_NEW_MSG, FALSE, &mii); } } // // FUNCTION: MenuUtil_ReplaceMessengerMenus // // PURPOSE: Customizes the Messenger menus with IEAK Messenger names... // void MenuUtil_ReplaceMessengerMenus(HMENU hMenu) { ULONG ulMenuItem; MENUITEMINFO mii; TCHAR szName[CCHMAX_STRINGRES]; for(ulMenuItem=ID_MESSENGER_FIRST;ulMenuItemGetDefaultAccount(fMail?ACCT_MAIL:ACCT_NEWS, &pAcct))) goto Exit; if (FAILED(pAcct->GetAccountType(&acctType))) goto Exit; if ((ACCT_NEWS != acctType) && SUCCEEDED(pAcct->GetServerTypes(&dwServerTypes)) && (dwServerTypes & SRV_POP3)) { *pFolderID = FOLDERID_LOCAL_STORE; goto Exit; } *szAccountId = 0; if (FAILED(pAcct->GetPropSz(AP_ACCOUNT_ID, szAccountId, ARRAYSIZE(szAccountId)))) goto Exit; if (FAILED(g_pStore->EnumChildren(FOLDERID_ROOT, TRUE, &pEnumFolders))) goto Exit; AssertSz(pAcct, "How did we succeed and not get a pAcct?"); AssertSz(pEnumFolders, "How did we succeed and not get a pEnumFolders?"); while (!fFound && (S_OK == pEnumFolders->Next(1, &rFolder, NULL))) { fFound = (0 == lstrcmp(szAccountId, rFolder.pszAccountId)); if (fFound) *pFolderID = rFolder.idFolder; g_pStore->FreeRecord(&rFolder); } Exit: ReleaseObj(pAcct); ReleaseObj(pEnumFolders); } // // FUNCTION: MenuUtil_HandleNewMessageIDs // // PURPOSE: Handles creation of notes from an ID // // RETURN VALUE: Returns TRUE if event was handled // BOOL MenuUtil_HandleNewMessageIDs(DWORD id, HWND hwnd, FOLDERID folderID, BOOL fMail, BOOL fModal, IUnknown *pUnkPump) { switch (id) { case ID_NEW_NEWS_MESSAGE: case ID_NEW_MAIL_MESSAGE: case ID_NEW_MSG_DEFAULT: { FOLDERINFO rInfo = {0}; if (id != ID_NEW_MSG_DEFAULT) fMail = (id == ID_NEW_MAIL_MESSAGE); if (SUCCEEDED(g_pStore->GetFolderInfo(folderID, &rInfo))) { BOOL fFolderIsMail = (rInfo.tyFolder != FOLDER_NEWS); if (fFolderIsMail != fMail) GetDefaultFolderID(fMail, &folderID); g_pStore->FreeRecord(&rInfo); } if (DwGetOption(fMail ? OPT_MAIL_USESTATIONERY : OPT_NEWS_USESTATIONERY)) { WCHAR wszFile[MAX_PATH]; if (SUCCEEDED(GetDefaultStationeryName(fMail, wszFile)) && SUCCEEDED(HrNewStationery(hwnd, 0, wszFile, fModal, fMail, folderID, FALSE, NSS_DEFAULT, pUnkPump, NULL))) { return TRUE; } // If HrNewStationery fails, go ahead and try opening a blank note without stationery. } FNewMessage(hwnd, fModal, !DwGetOption(fMail ? OPT_MAIL_SEND_HTML : OPT_NEWS_SEND_HTML), !fMail, folderID, pUnkPump); return TRUE; } case ID_STATIONERY_RECENT_0: case ID_STATIONERY_RECENT_1: case ID_STATIONERY_RECENT_2: case ID_STATIONERY_RECENT_3: case ID_STATIONERY_RECENT_4: case ID_STATIONERY_RECENT_5: case ID_STATIONERY_RECENT_6: case ID_STATIONERY_RECENT_7: case ID_STATIONERY_RECENT_8: case ID_STATIONERY_RECENT_9: HrNewStationery(hwnd, id, NULL, fModal, fMail, folderID, TRUE, NSS_MRU, pUnkPump, NULL); return TRUE; case ID_STATIONERY_MORE: HrMoreStationery(hwnd, fModal, fMail, folderID, pUnkPump); return TRUE; case ID_STATIONERY_NONE: FNewMessage(hwnd, fModal, TRUE, !fMail, folderID, pUnkPump); return TRUE; case ID_WEB_PAGE: HrSendWebPage(hwnd, fModal, fMail, folderID, pUnkPump); return TRUE; } return FALSE; } HRESULT MenuUtil_NewMessageIDsQueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText, BOOL fMail) { DWORD cMailServer = 0; DWORD cNewsServer = 0; DWORD cDefServer = 0; DWORD dwDefFlags; // For right now, NULL is acceptable. if (pguidCmdGroup && !IsEqualGUID(CMDSETID_OutlookExpress, *pguidCmdGroup)) return S_OK; g_pAcctMan->GetAccountCount(ACCT_NEWS, &cMailServer); g_pAcctMan->GetAccountCount(ACCT_MAIL, &cNewsServer); cDefServer = fMail ? cMailServer : cNewsServer; // If there is at least one server and we are not mail in news only mode if (!fMail || (0 == (g_dwAthenaMode & MODE_NEWSONLY))) dwDefFlags = OLECMDF_SUPPORTED | OLECMDF_ENABLED; else dwDefFlags = OLECMDF_SUPPORTED; for (UINT i = 0; i < cCmds; i++) { if (prgCmds[i].cmdf == 0) { switch (prgCmds[i].cmdID) { case ID_POPUP_NEW_MSG: case ID_NEW_MSG_DEFAULT: case ID_STATIONERY_RECENT_0: case ID_STATIONERY_RECENT_1: case ID_STATIONERY_RECENT_2: case ID_STATIONERY_RECENT_3: case ID_STATIONERY_RECENT_4: case ID_STATIONERY_RECENT_5: case ID_STATIONERY_RECENT_6: case ID_STATIONERY_RECENT_7: case ID_STATIONERY_RECENT_8: case ID_STATIONERY_RECENT_9: case ID_STATIONERY_MORE: case ID_STATIONERY_NONE: prgCmds[i].cmdf = dwDefFlags; break; case ID_WEB_PAGE: // If is enabled, then better make sure that we are on line. if ((dwDefFlags & OLECMDF_ENABLED) && g_pConMan->IsGlobalOffline()) prgCmds[i].cmdf = OLECMDF_SUPPORTED; else prgCmds[i].cmdf = dwDefFlags; break; case ID_NEW_MAIL_MESSAGE: if (!(g_dwAthenaMode & MODE_NEWSONLY)) prgCmds[i].cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED; else prgCmds[i].cmdf = OLECMDF_SUPPORTED; break; case ID_NEW_NEWS_MESSAGE: prgCmds[i].cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED; break; } } } return S_OK; } HRESULT MenuUtil_EnableMenu(HMENU hMenu, IOleCommandTarget *pTarget) { int Count; HMENU hMenuSub; HRESULT hr = S_OK; Count = GetMenuItemCount(hMenu); if (Count != -1) { while (--Count >= 0) { hMenuSub = GetSubMenu(hMenu, Count); hr = MenuUtil_EnablePopupMenu(hMenuSub, pTarget); } } else hr = E_FAIL; return hr; }