Add A Favorites Function to Your Menu

Environment: VC6 SP5,Win98 & Win2k

Do you want your program to read the users' Favorites/Bookmarks? Here is a simple and easy way to add a "Read my Favorites" function to your program based on CMenu class. After using CodeGuru.com almost everyday to help me learn C++ while designing JoeSwammi MLB (www.joeswammi.com), this is my small contibution.

  1. Insert a new menu IDR_FAVORITES_POPUP and make first topic ID_BOGUS

  2. Create your "Favorites" menu item in your IDR_MAINFRAME, in properties check mark it as a Pop-Up.

  3. Add
    #include <wininet.h>
    #include <shellapi.h>
    
    to MAINFRM.CPP

  4. Add
    CStringArray m_astrFavoriteURLs; 
    
    as a public variable in MAINFM.H

  5. Add this function to CMainFrame named:
    int CMainFrame::BuildFavoritesMenu(LPCTSTR pszPath, 
                                       int nStartPos, 
                                       CMenu *pMenu)
    {
      CString         strPath(pszPath);
      CString         strPath2;
      CString         str;
      WIN32_FIND_DATA wfd;
      HANDLE          h;
      int             nPos;
      int             nEndPos;
      int             nNewEndPos;
      int             nLastDir;
      TCHAR           buf[INTERNET_MAX_PATH_LENGTH];
      CStringArray    astrFavorites;
      CStringArray    astrDirs;
      CMenu*          pSubMenu;
    
      // make sure there's a trailing backslash
      if(strPath[strPath.GetLength() - 1] != _T('\\'))
        strPath += _T('\\');
      strPath2 = strPath;
      strPath += "*.*";
    
      // now scan the directory, first for .URL 
      // files and then for subdirectories
      // that may also contain .URL files
      h = FindFirstFile(strPath, &wfd);
      if(h != INVALID_HANDLE_VALUE)
      {
        nEndPos = nStartPos;
        do
        {
          if((wfd.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY|
                  FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM))==0)
          {
            str = wfd.cFileName;
            if(str.Right(4) == _T(".url"))
            {
              // an .URL file is formatted just like an .INI file,
              // so we can use GetPrivateProfileString() to get 
              // the information we want
              ::GetPrivateProfileString(_T("InternetShortcut"),
                                        _T("URL"),
                                        _T(""),
                                        buf,
                                        INTERNET_MAX_PATH_LENGTH,
                                        strPath2 + str);
              str = str.Left(str.GetLength() - 4);
    
              // scan through the array and perform an insertion
              // sort to make sure the menu ends up in alphabetic
              // order
              for(nPos = nStartPos ; nPos < nEndPos ; ++nPos)
              {
                if(str.CompareNoCase(astrFavorites[nPos]) < 0)
                  break;
              }
              astrFavorites.InsertAt(nPos, str);
              m_astrFavoriteURLs.InsertAt(nPos, buf);
              ++nEndPos;
            }
          }
        } while(FindNextFile(h, &wfd));
        FindClose(h);
        // Now add these items to the menu
        for(nPos = nStartPos ; nPos < nEndPos ; ++nPos)
        {
          pMenu->AppendMenu(MF_STRING | MF_ENABLED,
                            0xe00 + nPos,
                            astrFavorites[nPos]);
        }
    
        // now that we've got all the .URL files, check 
        // the subdirectories for more
        nLastDir = 0;
        h = FindFirstFile(strPath, &wfd);
        ASSERT(h != INVALID_HANDLE_VALUE);
        do
        {
          if(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
          {
            // ignore the current and parent directory entries
            if(lstrcmp(wfd.cFileName, 
    _T(".")) == 0 || lstrcmp(wfd.cFileName, _T("..")) == 0)
              continue;
    
            for(nPos = 0 ; nPos < nLastDir ; ++nPos)
            {
              if(astrDirs[nPos].CompareNoCase(wfd.cFileName) > 0)
                break;
            }
            pSubMenu = new CMenu;
            pSubMenu->CreatePopupMenu();
    
            // call this function recursively.
            nNewEndPos = BuildFavoritesMenu(strPath2 + wfd.cFileName,
                                            nEndPos,
                                            pSubMenu);
            if(nNewEndPos != nEndPos)
            {
              // only intert a submenu if there are in 
              // fact .URL files in the subdirectory
              nEndPos = nNewEndPos;
              pMenu->InsertMenu(nPos, 
                         MF_BYPOSITION | MF_POPUP | MF_STRING,
                         (UINT)pSubMenu->m_hMenu,
                         wfd.cFileName);
              pSubMenu->Detach();
              astrDirs.InsertAt(nPos, wfd.cFileName);
              ++nLastDir;
            }
            delete pSubMenu;
          }
        } while(FindNextFile(h, &wfd));
        FindClose(h);
      }
      return nEndPos;
    }
    
  6. Add this member function to CMainFrame named:
    void CMainFrame::OnFavorite(UINT nID)
    {
      ShellExecute(m_hWnd,
                   "open",
                   m_astrFavoriteURLs[nID-0xe00],
                   NULL,
                   NULL,
                   SW_SHOWDEFAULT);
    }
  7. In the ONCREATE function of CMainFrame, just before ending "return 0;", Add:
    // set up Favorites menu
      TCHAR           sz[MAX_PATH];
      TCHAR           szPath[MAX_PATH];
      HKEY            hKey;
      DWORD           dwSize;
      CMenu*          pMenu;
    
      // first get rid of bogus submenu items.
      pMenu = GetMenu()->GetSubMenu(3); //change three to what 
                        // ever position "Favorites" is from left - 1
      while(pMenu->DeleteMenu(0, MF_BYPOSITION));
    
      // find out from the registry where the favorites are located.
      if(RegOpenKey(HKEY_CURRENT_USER,
    _T("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User 
    Shell Folders"),
         &hKey) != ERROR_SUCCESS)
      {
        TRACE0("Favorites folder not found\n");
        return 0;
      }
      dwSize = sizeof(sz);
      RegQueryValueEx(hKey, _T("Favorites"), NULL, NULL, (LPBYTE)sz, &dwSize);
      ExpandEnvironmentStrings(sz, szPath, MAX_PATH);
      RegCloseKey(hKey);
    
      BuildFavoritesMenu(szPath, 0, pMenu);
  8. lastly, in the "BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)"add this line just above "END_MESSAGE_MAP()":
    ON_COMMAND_RANGE(0xe00, 0xfff, OnFavorite)
  9. Build and Run and should work.

NOTE: I am sure there are other features I am missing. For example, icons to go with the pop-ups next to the bookmarks, like folders and html icon, more like MS IE. If you develope this code, Please add your code to the comments for others to use also. Thanks.

Downloads

Download demo project - 22.7 Kb
Download source - All Source on this page (Cut & Paste)


Comments

  • How do you implement Add to favorites in MFC?

    Posted by Legacy on 09/14/2003 12:00am

    Originally posted by: Mike Hardy

    I am writting a Webbrowser in VC++ 6.0 standard Edition using MFC and I have already implemented View your Favorites I would like to know how I can call the Add to Favorites dialog where the user can Add a Site to the favorites menu. Can anyone help me please. if so email me or reply here my email is scoobyto@fidnet.com any one that can help will recieve the Source Code to my Webbrowser. Thanks sincerely, Mike Hardy
    

    Reply
  • bugs in Visual C++.net

    Posted by Legacy on 11/19/2002 12:00am

    Originally posted by: Richard H

    Try building this in Visual C++ .net.......
    
    

    I'm having problems with the .exe file which balks on memory problems.

    Any ideas?

    Reply
  • MFCIE?

    Posted by Legacy on 05/13/2002 12:00am

    Originally posted by: Allen

    Isn't that the code from MFCIE from MSDN?

    http://msdn.microsoft.com/code/default.asp?url=/msdn-files/026/001/497/Source%20Files/MainFrm_cpp.asp

    Reply
  • Thanks

    Posted by Legacy on 03/17/2002 12:00am

    Originally posted by: Bug Alert

    Thanks again

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Companies undertaking an IT project need to find the right balance between cost and functionality. It's important to start by determining whether to build a solution from scratch, buy an out-of-the-box solution, or a combination of both. In reality, most projects will require some system tailoring to meet business requirements. Decision-makers must understand how much software development is enough and craft a detailed implementation plan to ensure the project's success. This white paper examines the different …

  • According to technology research firm Gartner, cloud computing will become the bulk of new IT spend by 20161. By the end of 2017, Gartner predicts that nearly half of large enterprises will have hybrid cloud deployments1. Learn how you can use these trends to your advantage by offering cloud and hybrid data solutions to your customers.

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date