windows-nt/Source/XPSP1/NT/shell/browseui/mrulist.cpp

918 lines
26 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/**************************************************************\
FILE: mrulist.cpp
DESCRIPTION:
CMRUList implements the Shell Name Space List or DriveList.
This will store a pidl and be able to populate the AddressBand
combobox with the shell name space that includes that PIDL.
\**************************************************************/
#include "priv.h"
#include "addrlist.h"
#include "itbar.h"
#include "itbdrop.h"
#include "util.h"
#include "autocomp.h"
#include <urlhist.h>
#include <winbase.h>
#include <wininet.h>
#define SUPERCLASS CAddressList
///////////////////////////////////////////////////////////////////
// #DEFINEs
#define MRU_LIST_MAX_CONST 25
///////////////////////////////////////////////////////////////////
// Data Structures
typedef struct tagSIZESTRCOMBO
{
DWORD dwStringSize; // Size in Characters (not bytes)
LPTSTR lpszString;
int iImage;
int iSelectedImage;
} SIZESTRCOMBO;
///////////////////////////////////////////////////////////////////
// Prototypes
/**************************************************************\
CLASS: CMRUList
DESCRIPTION:
The MRU List will contain the type MRU history for the
browser. This is an IAddressList used by the Address Band/Bar.
\**************************************************************/
class CMRUList : public CAddressList
, public IMRU
, public IPersistStream
{
public:
//////////////////////////////////////////////////////
// Public Interfaces
//////////////////////////////////////////////////////
// *** IUnknown ***
virtual STDMETHODIMP_(ULONG) AddRef(void);
virtual STDMETHODIMP_(ULONG) Release(void);
virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);
// *** IAddressList methods ***
virtual STDMETHODIMP Connect(BOOL fConnect, HWND hwnd, IBrowserService * pbs, IBandProxy * pbp, IAutoComplete * pac);
virtual STDMETHODIMP Refresh(DWORD dwType);
virtual STDMETHODIMP Save(void);
// *** IPersistStream methods ***
virtual STDMETHODIMP GetClassID(CLSID *pClassID){ *pClassID = CLSID_MRUList; return S_OK; }
virtual STDMETHODIMP Load(IStream *pStm) { return S_OK; }
virtual STDMETHODIMP Save(IStream *pStm, BOOL fClearDirty);
virtual STDMETHODIMP IsDirty(void) { return S_FALSE; }
virtual STDMETHODIMP GetSizeMax(ULARGE_INTEGER *pcbSize) { return E_NOTIMPL; }
// *** IMRU methods ***
virtual STDMETHODIMP AddEntry(LPCWSTR pszEntry);
// IWinEventHandler
virtual STDMETHODIMP OnWinEvent(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plres);
protected:
//////////////////////////////////////////////////////
// Private Member Functions
//////////////////////////////////////////////////////
// Constructor / Destructor
CMRUList();
~CMRUList(void); // This is now an OLE Object and cannot be used as a normal Class.
// Address List Modification Functions
HRESULT _UpdateMRUEntry(LPCTSTR szNewValue, int nIndex, int iImage , int iISelectedImage);
HRESULT _LoadList(void);
HKEY _GetRegKey(BOOL fCreate);
HRESULT _UpdateMRU(void);
int _FindInMRU(LPCTSTR szURL);
HRESULT _MRUMerge(HKEY kKey);
BOOL _MoveAddressToTopOfMRU(int nMRUIndex);
HRESULT _PopulateOneItem(void);
HRESULT _Populate(void);
void _InitCombobox(void);
HRESULT _SetTopItem(void);
// Friend Functions
friend IAddressList * CMRUList_Create(void);
//////////////////////////////////////////////////////
// Private Member Variables
//////////////////////////////////////////////////////
BOOL _fDropDownPopulated;// Have we populated the drop down yet?
BOOL _fListLoaded; // Have we loaded the Type-in MRU?
BOOL _fMRUUptodate; // Is it necessary to update the MRU?
BOOL _fNeedToSave; // Do we need to update the registry?
SIZESTRCOMBO _szMRU[MRU_LIST_MAX_CONST]; // MRU list.
int _nMRUSize; // Number of entries in MRU used.
};
//=================================================================
// Implementation of CMRUList
//=================================================================
/****************************************************\
FUNCTION: CMRUList_Create
DESCRIPTION:
This function will create an instance of the
CMRUList COM object.
\****************************************************/
IAddressList * CMRUList_Create(void)
{
CMRUList *p = new CMRUList();
return p;
}
/****************************************************\
Address Band Constructor
\****************************************************/
CMRUList::CMRUList()
{
}
/****************************************************\
Address Band destructor
\****************************************************/
CMRUList::~CMRUList()
{
// loop through every potential saved URL in registry.
if (_fListLoaded)
{
for (int nIndex = 0; (nIndex < MRU_LIST_MAX_CONST) && (_szMRU[nIndex].lpszString); nIndex++)
{
LocalFree(_szMRU[nIndex].lpszString);
}
}
}
//===========================
// *** IUnknown Interface ***
HRESULT CMRUList::QueryInterface(REFIID riid, void **ppvObj)
{
if (IsEqualIID(riid, IID_IMRU))
{
*ppvObj = SAFECAST(this, IMRU*);
}
else if (IsEqualIID(riid, IID_IPersistStream))
{
*ppvObj = SAFECAST(this, IPersistStream*);
}
else
{
return SUPERCLASS::QueryInterface(riid,ppvObj);
}
AddRef();
return S_OK;
}
ULONG CMRUList::AddRef()
{
return SUPERCLASS::AddRef();
}
ULONG CMRUList::Release()
{
return SUPERCLASS::Release();
}
//================================
// *** IAddressList Interface ***
/****************************************************\
FUNCTION: Connect
DESCRIPTION:
We are either becoming the selected list for
the AddressBand's combobox, or lossing this status.
We need to populate or unpopulate the combobox
as appropriate.
\****************************************************/
HRESULT CMRUList::Connect(BOOL fConnect, HWND hwnd, IBrowserService * pbs, IBandProxy * pbp, IAutoComplete * pac)
{
HRESULT hr = S_OK;
_fVisible = fConnect;
if (!_hwnd)
_hwnd = hwnd;
ASSERT(_hwnd);
if (fConnect)
{
// This needs to come before because it setups up
// pointers that we need.
SUPERCLASS::Connect(fConnect, hwnd, pbs, pbp, pac);
// Initial combobox parameters.
if (_pbp && _pbp->IsConnected() == S_FALSE)
{
// Do these tasks only the first time and only if
// we are not in a browser window (because it will come
// from the navigation complete).
_PopulateOneItem();
}
}
else
{
_UpdateMRU(); // Save contents of MRU because the ComboBox will be purged.
_fDropDownPopulated = FALSE;
// This call needs to come after _UpdateMRU() because
// it releases pointers that we need.
SUPERCLASS::Connect(fConnect, hwnd, pbs, pbp, pac);
}
return hr;
}
/****************************************************\
FUNCTION: _SetTopItem
DESCRIPTION:
TODO.
\****************************************************/
HRESULT CMRUList::_SetTopItem(void)
{
COMBOBOXEXITEM cbexItem = {0};
LPCTSTR pszData = _szMRU[0].lpszString;
if (pszData) {
cbexItem.mask = CBEIF_TEXT | CBEIF_IMAGE | CBEIF_SELECTEDIMAGE;
cbexItem.iItem = -1;
cbexItem.pszText =(LPTSTR)pszData;
cbexItem.cchTextMax = lstrlen(pszData);
if(_szMRU[0].iImage == -1 || _szMRU[0].iSelectedImage == -1) {
_GetUrlUI(NULL,pszData, &(_szMRU[0].iImage),\
&(_szMRU[0].iSelectedImage));
}
cbexItem.iImage =_szMRU[0].iImage;
cbexItem.iSelectedImage = _szMRU[0].iSelectedImage;
SendMessage(_hwnd, CBEM_SETITEM, (WPARAM)0, (LPARAM)(LPVOID)&cbexItem);
}
return S_OK;
}
//================================
// *** IMRU Interface ***
/*******************************************************************
FUNCTION: AddEntry
DESCRIPTION:
Adds the specified URL to the top of the address bar
combo box. Limits the number of URLs in combo box to
MRU_LIST_MAX_CONST.
********************************************************************/
HRESULT CMRUList::AddEntry(LPCWSTR pszEntry)
{
HRESULT hr = S_OK;
_fNeedToSave = TRUE;
if (_fDropDownPopulated)
{
_ComboBoxInsertURL(pszEntry, MAX_URL_STRING, MRU_LIST_MAX_CONST);
_fMRUUptodate = FALSE;
}
else
{
int nMRUIndex;
if (!_fListLoaded)
_LoadList();
// Since we don't own the ComboBox, we need to add it to
// the end of our MRU data.
nMRUIndex = _FindInMRU(pszEntry); // Now make it the top most.
if (-1 != nMRUIndex)
{
// We already have this entry in our list, so all we need
// to do is move it to the top.
_MoveAddressToTopOfMRU(nMRUIndex);
return hr;
}
for (nMRUIndex = 0; nMRUIndex < MRU_LIST_MAX_CONST; nMRUIndex++)
{
if (!_szMRU[nMRUIndex].lpszString)
{ // We found an empty spot.
_UpdateMRUEntry(pszEntry, nMRUIndex, -1, -1);
break; // We are done.
}
}
if (MRU_LIST_MAX_CONST == nMRUIndex)
{
// The MRU is full so we will replace the last entry.
_UpdateMRUEntry(pszEntry, --nMRUIndex, -1, -1);
}
_MoveAddressToTopOfMRU(nMRUIndex); // Now make it the top most.
}
TraceMsg(TF_BAND|TF_GENERAL, "CMRUList: AddEntry(), URL=%s", pszEntry);
return hr;
}
//================================
// *** IPersistStream Interface ***
/****************************************************\
FUNCTION: Save
DESCRIPTION:
TODO.
\****************************************************/
HRESULT CMRUList::Save(IStream *pstm, BOOL fClearDirty)
{
// APPCOMPAT: There currently is a bug in the shell that it leaks
// an object. This causes CAddressBand to never be
// destructed when hosted in the TaskBar.
// Since we normally call IAddressList::SaveList() in the
// destructor, we will now need to call it
// from here in that case.
if (_pbp && _pbp->IsConnected() == S_FALSE)
{
Save();
}
return S_OK;
}
/****************************************************\
FUNCTION: _InitCombobox
DESCRIPTION:
Prepare the combo box for this list. This normally
means that the indenting and icon are either turned
on or off.
\****************************************************/
void CMRUList::_InitCombobox()
{
HIMAGELIST himlSysSmall;
Shell_GetImageLists(NULL, &himlSysSmall);
SendMessage(_hwnd, CBEM_SETIMAGELIST, 0, (LPARAM)himlSysSmall);
SendMessage(_hwnd, CBEM_SETEXTENDEDSTYLE, 0,0);
SUPERCLASS::_InitCombobox();
}
HKEY CMRUList::_GetRegKey(BOOL fCreate)
{
BOOL fIsConnected = FALSE;
HKEY hKey;
DWORD result;
LPCTSTR pszKey;
if (_pbp)
fIsConnected = (_pbp->IsConnected() == S_OK);
if (fIsConnected)
pszKey = SZ_REGKEY_TYPEDURLMRU;
else
pszKey = SZ_REGKEY_TYPEDCMDMRU;
if (fCreate)
result = RegCreateKey(HKEY_CURRENT_USER, pszKey, &hKey);
else
result = RegOpenKey(HKEY_CURRENT_USER, pszKey, &hKey);
if (result != ERROR_SUCCESS)
return NULL;
return hKey;
}
/****************************************************\
FUNCTION: _LoadList
DESCRIPTION:
When the ComboBox is switched to this MRU
AddressList, the contents need to be populated. Before
that happens, we copy the data to the combobox
from the registry.
\****************************************************/
HRESULT CMRUList::_LoadList(void)
{
HRESULT hr = S_OK;
HKEY hKey;
DWORD dwCount;
TCHAR szAddress[MAX_URL_STRING+1];
ASSERT(!_fListLoaded);
ASSERT(_hwnd);
hKey = _GetRegKey(TRUE);
ASSERT(hKey);
if (!hKey)
return E_FAIL;
for (dwCount = 0; dwCount < MRU_LIST_MAX_CONST ; dwCount++)
{
hr = GetMRUEntry(hKey, dwCount, szAddress, SIZECHARS(szAddress), NULL);
if (SUCCEEDED(hr))
_UpdateMRUEntry(szAddress, (int)dwCount, -1, -1);
else
{
_szMRU[dwCount].lpszString = NULL;
_szMRU[dwCount].iImage = -1;
_szMRU[dwCount].iSelectedImage = -1;
}
}
RegCloseKey(hKey);
_fListLoaded = TRUE;
return hr;
}
/****************************************************\
FUNCTION: Save
DESCRIPTION:
When this object is closed, we save the contents
to the registry.
\****************************************************/
HRESULT CMRUList::Save(void)
{
HRESULT hr = S_OK;
HKEY hKey;
DWORD result;
TCHAR szValueName[10]; // big enough for "url99"
int nCount;
int nItems = (_fDropDownPopulated) ? ComboBox_GetCount(_hwnd) : _nMRUSize;
if (!_fListLoaded || !_fNeedToSave) // Don't save the registry if we don't need to.
return S_OK;
if (!_fMRUUptodate)
hr = _UpdateMRU();
hKey = _GetRegKey(TRUE);
ASSERT(hKey);
if (!hKey)
return E_FAIL;
hr = _MRUMerge(hKey); // Merge if the list has been modified.
// loop through every potential saved URL in registry.
for (nCount = 0; nCount < MRU_LIST_MAX_CONST; nCount++)
{
// make a value name a la "url1" (1-based for historical reasons)
wnsprintf(szValueName, ARRAYSIZE(szValueName), SZ_REGVAL_MRUENTRY, nCount+1);
// for every combo box item we have, get the corresponding
// text and save it in the registry
if (nCount < nItems && _szMRU[nCount].lpszString)
{
// store it in registry and off to the next one.
result = SHSetValue(hKey, NULL, szValueName, REG_SZ, (CONST BYTE *) _szMRU[nCount].lpszString,
_szMRU[nCount].dwStringSize*SIZEOF(TCHAR));
}
else
{
// if we get here, we've run out of combo box items (or
// failed to retrieve text for one of them). Delete any
// extra items that may be lingering in the registry.
SHDeleteValue(hKey, NULL, szValueName);
}
}
_fNeedToSave = FALSE;
RegCloseKey(hKey);
return hr;
}
/****************************************************\
FUNCTION: _MRUMerge
DESCRIPTION:
This function will merge the current contents
of the saved MRU. This means that if the Address
Band is being closed, it will load the MRU again
because it could have been saved by a AddressBar
that was recently closed down. The merge happens
like this: If the MRU is not full, items
in the registry will be appended to the end
of the MRU if they don't currently exist in the
MRU.
\****************************************************/
HRESULT CMRUList::_MRUMerge(HKEY hKey)
{
HRESULT hr = S_OK;
UINT nCount;
UINT nNextFreeSlot = _nMRUSize;
long lResult;
TCHAR szValueName[10]; // big enough for "url99"
TCHAR szAddress[MAX_URL_STRING+1];
DWORD dwAddress;
ASSERT(_fListLoaded);
ASSERT(hKey);
for (nCount = 0; (nCount < MRU_LIST_MAX_CONST) && (nNextFreeSlot < MRU_LIST_MAX_CONST); nCount++)
{
// make a value name a la "url1" (1-based for historical reasons)
wnsprintf(szValueName, ARRAYSIZE(szValueName), SZ_REGVAL_MRUENTRY, nCount+1);
dwAddress = SIZEOF(szAddress);
lResult = SHQueryValueEx(hKey, szValueName, NULL, NULL, (LPBYTE) szAddress, &dwAddress);
if (ERROR_SUCCESS == lResult)
{
if (-1 == _FindInMRU(szAddress))
{
// We found a unique item. Add it to our free slot.
_UpdateMRUEntry(szAddress, nNextFreeSlot++, -1, -1);
}
}
else
break;
}
// REARCHITECT: Because the AddressBand is always closed after all
// AddressBars when the shell is shut down, anything
// new in the AddressBars will be ignored if the
// MRU in the AddressBand is full. Revisit.
return hr;
}
/****************************************************\
FUNCTION: _UpdateMRU
DESCRIPTION:
Save the contents of the Combobox because
it will be purged for the next AddressList.
\****************************************************/
HRESULT CMRUList::_UpdateMRU(void)
{
HRESULT hr = S_OK;
TCHAR szAddress[MAX_URL_STRING+1];
// get the number of items in combo box
int nItems;
int nCount;
if (!_hwnd)
return S_OK;
if (!_fDropDownPopulated)
return S_OK; // Nothing to update.
nItems = ComboBox_GetCount(_hwnd);
ASSERT(_hwnd);
// loop through every potential saved URL in registry.
for (nCount = 0; nCount < MRU_LIST_MAX_CONST; nCount++)
{
// for every combo box item we have, get the corresponding
// text and save it in our local array.
if (nCount < nItems)
{
COMBOBOXEXITEM cbexItem = {0};
cbexItem.mask = CBEIF_TEXT|CBEIF_IMAGE|CBEIF_SELECTEDIMAGE;
cbexItem.pszText = szAddress;
cbexItem.cchTextMax = ARRAYSIZE(szAddress);
cbexItem.iItem = nCount;
if (SendMessage(_hwnd, CBEM_GETITEM, 0, (LPARAM) &cbexItem))
{
hr = _UpdateMRUEntry(szAddress, nCount, cbexItem.iImage, cbexItem.iSelectedImage);
}
}
else
{
if (_szMRU[nCount].lpszString)
{
// Free this array entry because it's not being used.
LocalFree(_szMRU[nCount].lpszString);
_szMRU[nCount].lpszString = NULL;
_szMRU[nCount].iImage = -1;
_szMRU[nCount].iSelectedImage = -1;
_nMRUSize--;
}
}
}
_fMRUUptodate = TRUE;
TraceMsg(TF_BAND|TF_GENERAL, "CMRUList: _UpdateMRU().");
return hr;
}
/****************************************************\
FUNCTION: _UpdateMRUEntry
DESCRIPTION:
When the ComboBox is switched to this MRU
AddressList, the contents need to be populated. Before
that happens, we copy the data to the combobox
from the registry.
\****************************************************/
HRESULT CMRUList::_UpdateMRUEntry(LPCTSTR szNewValue, int nIndex, int iImage , int iSelectedImage)
{
DWORD dwStrSize = lstrlen(szNewValue);
if (!szNewValue)
{
// The caller wants us to free the string.
if (_szMRU[nIndex].lpszString)
{
// We have a string that needs freeing.
LocalFree(_szMRU[nIndex].lpszString);
_szMRU[nIndex].lpszString = NULL;
_nMRUSize--;
}
return S_OK;
}
if (!(_szMRU[nIndex].lpszString))
{
// We need to create the string buffer
_szMRU[nIndex].dwStringSize = dwStrSize+1;
_szMRU[nIndex].lpszString = (LPTSTR) LocalAlloc(LPTR, _szMRU[nIndex].dwStringSize*SIZEOF(TCHAR));
if (!(_szMRU[nIndex].lpszString))
return E_FAIL;
_nMRUSize++;
}
if (dwStrSize + 1 > _szMRU[nIndex].dwStringSize)
{
// We need to increase the size of the buffer.
LocalFree(_szMRU[nIndex].lpszString);
_szMRU[nIndex].dwStringSize = dwStrSize+1;
_szMRU[nIndex].lpszString = (LPTSTR) LocalAlloc(LPTR, _szMRU[nIndex].dwStringSize*SIZEOF(TCHAR));
if (!(_szMRU[nIndex].lpszString))
return E_FAIL;
}
lstrcpyn(_szMRU[nIndex].lpszString, szNewValue, _szMRU[nIndex].dwStringSize);
_szMRU[nIndex].iImage = iImage;
_szMRU[nIndex].iSelectedImage = iSelectedImage;
return S_OK;
}
/****************************************************\
FUNCTION: _Populate
DESCRIPTION:
fills in the entire combo.
WARNING!!!!!!!!:
This is expensive, don't do it unless absolutely
necessary!
\****************************************************/
HRESULT CMRUList::_Populate(void)
{
HRESULT hr = S_OK;
CShellUrl *psu;
if (!_fListLoaded)
hr = _LoadList(); // Load Data
if (_fDropDownPopulated)
return S_OK; // We are already populated.
psu = new CShellUrl();
if (psu)
{
// We need to set the "Shell Path" so that we can find
// the correct icons for items in "desktop" and in
// Desktop/My Computer".
SetDefaultShellPath(psu);
// Give it a parent for displaying message boxes
psu->SetMessageBoxParent(_hwnd);
// read values from registry and put them in combo box
COMBOBOXEXITEM cbexItem = {0};
cbexItem.mask = CBEIF_TEXT | CBEIF_IMAGE | CBEIF_SELECTEDIMAGE;
for (cbexItem.iItem = 0; cbexItem.iItem < MRU_LIST_MAX_CONST ; cbexItem.iItem++)
{
if (_szMRU[cbexItem.iItem].lpszString)
{
cbexItem.pszText = _szMRU[cbexItem.iItem].lpszString;
cbexItem.cchTextMax = _szMRU[cbexItem.iItem].dwStringSize;
//Do Image creation when we actually populate
if(_szMRU[cbexItem.iItem].iImage == -1 || _szMRU[cbexItem.iItem].iSelectedImage == -1) {
_GetUrlUI(psu,_szMRU[cbexItem.iItem].lpszString, &(_szMRU[cbexItem.iItem].iImage),\
&(_szMRU[cbexItem.iItem].iSelectedImage));
}
// initialize the image indexes
cbexItem.iImage = _szMRU[cbexItem.iItem].iImage;
cbexItem.iSelectedImage = _szMRU[cbexItem.iItem].iSelectedImage;
SendMessage(_hwnd, CBEM_INSERTITEM, (WPARAM)0, (LPARAM)(LPVOID)&cbexItem);
}
else
break; // Stop populating when we hit the max.
}
_fDropDownPopulated = TRUE;
//Delete the shell url object
delete psu;
} else {
// low mem
hr = E_OUTOFMEMORY;
}
TraceMsg(TF_BAND|TF_GENERAL, "CMRUList: _Populate(). This is a VERY EXPENSIVE operation.");
return hr;
}
/****************************************************\
FUNCTION: _PopulateOneItem
DESCRIPTION:
This just files the ComboBox's edit control.
We do this when we want to postpone populating
the entire drop down list.
\****************************************************/
HRESULT CMRUList::_PopulateOneItem(void)
{
HRESULT hr = S_OK;
if (!_fListLoaded)
hr = _LoadList(); // Load Data
if (_fDropDownPopulated)
return S_OK; // We are already populated.
hr = _SetTopItem();
return hr;
}
/****************************************************\
FUNCTION: Refresh
DESCRIPTION:
Update the URL in the Top of the list.
\****************************************************/
HRESULT CMRUList::Refresh(DWORD dwType)
{
HRESULT hr = S_OK;
if (OLECMD_REFRESH_ENTIRELIST == dwType)
{
// Force a refresh. We don't move the contents
// of the of the Combobox to the MRU because the
// user wanted to refresh the Combobox because
// it's contents may be tainted.
SendMessage(_hwnd, CB_RESETCONTENT, 0, 0L);
_fDropDownPopulated = FALSE;
}
return hr;
}
//================================
// *** Internal/Private Methods ***
/*******************************************************************
FUNCTION: _MoveAddressToTopOfMRU
PARAMETERS:
nMRUIndex - index of be moved to top.
DESCRIPTION:
This function will move the specified index to the top of
the list.
********************************************************************/
BOOL CMRUList::_MoveAddressToTopOfMRU(int nMRUIndex)
{
int nCurrent;
SIZESTRCOMBO sscNewTopItem;
_fNeedToSave = TRUE;
ASSERT(nMRUIndex < MRU_LIST_MAX_CONST);
// Save off new top item info.
sscNewTopItem.dwStringSize = _szMRU[nMRUIndex].dwStringSize;
sscNewTopItem.lpszString = _szMRU[nMRUIndex].lpszString;
sscNewTopItem.iImage = _szMRU[nMRUIndex].iImage;
sscNewTopItem.iSelectedImage = _szMRU[nMRUIndex].iSelectedImage;
for (nCurrent = nMRUIndex; nCurrent > 0; nCurrent--)
{
// Move item down in list.
_szMRU[nCurrent].dwStringSize = _szMRU[nCurrent-1].dwStringSize;
_szMRU[nCurrent].lpszString = _szMRU[nCurrent-1].lpszString;
_szMRU[nCurrent].iImage = _szMRU[nCurrent-1].iImage;
_szMRU[nCurrent].iSelectedImage = _szMRU[nCurrent-1].iSelectedImage;
}
// Set new top item.
_szMRU[0].dwStringSize = sscNewTopItem.dwStringSize;
_szMRU[0].lpszString = sscNewTopItem.lpszString;
_szMRU[0].iImage = sscNewTopItem.iImage;
_szMRU[0].iSelectedImage = sscNewTopItem.iSelectedImage;
return TRUE;
}
/*******************************************************************
FUNCTION: _FindInMRU
PARAMETERS:
szURL - URL to see if it exists in list.
DESCRIPTION:
Search through MRU for URL. Return value will be -1 if not
found or index if found.
********************************************************************/
int CMRUList::_FindInMRU(LPCTSTR szURL)
{
int nCurrent;
for (nCurrent = 0; (nCurrent < MRU_LIST_MAX_CONST) && _szMRU[nCurrent].lpszString; nCurrent++)
{
if (0 == StrCmpN(_szMRU[nCurrent].lpszString, szURL, _szMRU[nCurrent].dwStringSize))
{
// We found it.
return nCurrent;
}
}
return -1;
}
HRESULT CMRUList::OnWinEvent(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plres)
{
switch(uMsg) {
case WM_WININICHANGE:
{
HKEY hkey = _GetRegKey(FALSE);
if (hkey) {
RegCloseKey(hkey);
} else {
// reset if the key is gone
if (_fVisible) {
SendMessage(_hwnd, CB_RESETCONTENT, 0, 0L);
}
_fDropDownPopulated = FALSE;
_fListLoaded = FALSE;
}
}
break;
}
return SUPERCLASS::OnWinEvent(hwnd, uMsg, wParam, lParam, plres);
}