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)

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read