mirror of
https://github.com/reactos/reactos.git
synced 2024-07-14 00:25:05 +00:00
[BROWSEUI] -CAddressEditBox: Populate address bar combobox. Patch by Barrett Karish with improvements by me to fix leaks and add error checks. CORE-10988
svn path=/trunk/; revision=75670
This commit is contained in:
parent
58ef11fbed
commit
9cf9a89aa0
|
@ -26,21 +26,22 @@ This class handles the combo box of the address band.
|
|||
|
||||
/*
|
||||
TODO:
|
||||
Handle listbox dropdown message and fill contents
|
||||
Add drag and drop of icon in edit box
|
||||
Handle change notifies to update appropriately
|
||||
Fix so selection in combo listbox navigates
|
||||
*/
|
||||
|
||||
CAddressEditBox::CAddressEditBox() :
|
||||
fCombobox(NULL, this, 1),
|
||||
fEditWindow(NULL, this, 1),
|
||||
fSite(NULL)
|
||||
fSite(NULL),
|
||||
pidlLastParsed(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
CAddressEditBox::~CAddressEditBox()
|
||||
{
|
||||
if (pidlLastParsed)
|
||||
ILFree(pidlLastParsed);
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CAddressEditBox::SetOwner(IUnknown *pOwner)
|
||||
|
@ -74,6 +75,7 @@ HRESULT STDMETHODCALLTYPE CAddressEditBox::Init(HWND comboboxEx, HWND editContro
|
|||
fCombobox.SubclassWindow(comboboxEx);
|
||||
fEditWindow.SubclassWindow(editControl);
|
||||
fSite = param18;
|
||||
hComboBoxEx = comboboxEx;
|
||||
|
||||
SHAutoComplete(fEditWindow.m_hWnd, SHACF_FILESYSTEM | SHACF_URLALL | SHACF_USETAB);
|
||||
|
||||
|
@ -258,7 +260,18 @@ HRESULT STDMETHODCALLTYPE CAddressEditBox::OnWinEvent(
|
|||
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_COMMAND:
|
||||
{
|
||||
if (HIWORD(wParam) == CBN_SELCHANGE)
|
||||
{
|
||||
UINT selectedIndex = SendMessageW((HWND)lParam, CB_GETCURSEL, 0, 0);
|
||||
pidlLastParsed = ILClone((LPITEMIDLIST)SendMessageW((HWND)lParam, CB_GETITEMDATA, selectedIndex, 0));
|
||||
Execute(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_NOTIFY:
|
||||
{
|
||||
hdr = (LPNMHDR) lParam;
|
||||
if (hdr->code == CBEN_ENDEDIT)
|
||||
{
|
||||
|
@ -272,8 +285,18 @@ HRESULT STDMETHODCALLTYPE CAddressEditBox::OnWinEvent(
|
|||
/* Reset the contents of the combo box */
|
||||
}
|
||||
}
|
||||
else if (hdr->code == CBEN_DELETEITEM)
|
||||
{
|
||||
PNMCOMBOBOXEX pCBEx = (PNMCOMBOBOXEX) lParam;
|
||||
LPITEMIDLIST itemPidl = (LPITEMIDLIST)pCBEx->ceItem.lParam;
|
||||
if (itemPidl)
|
||||
{
|
||||
ILFree(itemPidl);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -320,12 +343,8 @@ HRESULT STDMETHODCALLTYPE CAddressEditBox::Invoke(DISPID dispIdMember, REFIID ri
|
|||
CComPtr<IBrowserService> isb;
|
||||
CComPtr<IShellFolder> sf;
|
||||
HRESULT hr;
|
||||
INT indexClosed, indexOpen, itemExists, oldIndex;
|
||||
DWORD result;
|
||||
COMBOBOXEXITEMW item;
|
||||
PIDLIST_ABSOLUTE absolutePIDL;
|
||||
LPCITEMIDLIST pidlChild;
|
||||
LPITEMIDLIST pidlPrevious;
|
||||
STRRET ret;
|
||||
WCHAR buf[4096];
|
||||
|
||||
|
@ -336,23 +355,12 @@ HRESULT STDMETHODCALLTYPE CAddressEditBox::Invoke(DISPID dispIdMember, REFIID ri
|
|||
{
|
||||
case DISPID_NAVIGATECOMPLETE2:
|
||||
case DISPID_DOCUMENTCOMPLETE:
|
||||
|
||||
if (pidlLastParsed)
|
||||
ILFree(pidlLastParsed);
|
||||
pidlLastParsed = NULL;
|
||||
|
||||
oldIndex = fCombobox.SendMessage(CB_GETCURSEL, 0, 0);
|
||||
|
||||
itemExists = FALSE;
|
||||
pidlPrevious = NULL;
|
||||
|
||||
ZeroMemory(&item, sizeof(item));
|
||||
item.mask = CBEIF_LPARAM;
|
||||
item.iItem = 0;
|
||||
if (fCombobox.SendMessage(CBEM_GETITEM, 0, reinterpret_cast<LPARAM>(&item)))
|
||||
{
|
||||
pidlPrevious = reinterpret_cast<LPITEMIDLIST>(item.lParam);
|
||||
if (pidlPrevious)
|
||||
itemExists = TRUE;
|
||||
}
|
||||
|
||||
/* Get the current pidl of the browser */
|
||||
hr = IUnknown_QueryService(fSite, SID_STopLevelBrowser, IID_PPV_ARG(IBrowserService, &isb));
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
@ -361,6 +369,28 @@ HRESULT STDMETHODCALLTYPE CAddressEditBox::Invoke(DISPID dispIdMember, REFIID ri
|
|||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
/* Fill the combobox */
|
||||
PopulateComboBox(absolutePIDL);
|
||||
|
||||
/* Find the current item in the combobox and select it */
|
||||
CComPtr<IShellFolder> psfDesktop;
|
||||
hr = SHGetDesktopFolder(&psfDesktop);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return S_OK;
|
||||
|
||||
hr = psfDesktop->GetDisplayNameOf(absolutePIDL, SHGDN_FORADDRESSBAR, &ret);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return S_OK;
|
||||
|
||||
hr = StrRetToBufW(&ret, absolutePIDL, buf, 4095);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return S_OK;
|
||||
|
||||
int index = SendMessageW(hComboBoxEx, CB_FINDSTRINGEXACT, 0, (LPARAM)buf);
|
||||
if (index != -1)
|
||||
SendMessageW(hComboBoxEx, CB_SETCURSEL, index, 0);
|
||||
|
||||
/* Add the item that will be visible when the combobox is not expanded */
|
||||
hr = SHBindToParent(absolutePIDL, IID_PPV_ARG(IShellFolder, &sf), &pidlChild);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
@ -373,37 +403,17 @@ HRESULT STDMETHODCALLTYPE CAddressEditBox::Invoke(DISPID dispIdMember, REFIID ri
|
|||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
INT indexClosed, indexOpen;
|
||||
indexClosed = SHMapPIDLToSystemImageListIndex(sf, pidlChild, &indexOpen);
|
||||
|
||||
COMBOBOXEXITEMW item = {0};
|
||||
item.mask = CBEIF_IMAGE | CBEIF_SELECTEDIMAGE | CBEIF_TEXT | CBEIF_LPARAM;
|
||||
item.iItem = 0;
|
||||
item.iItem = -1;
|
||||
item.iImage = indexClosed;
|
||||
item.iSelectedImage = indexOpen;
|
||||
item.pszText = buf;
|
||||
item.lParam = reinterpret_cast<LPARAM>(absolutePIDL);
|
||||
|
||||
if (itemExists)
|
||||
{
|
||||
result = fCombobox.SendMessage(CBEM_SETITEM, 0, reinterpret_cast<LPARAM>(&item));
|
||||
oldIndex = 0;
|
||||
|
||||
if (result)
|
||||
{
|
||||
ILFree(pidlPrevious);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
oldIndex = fCombobox.SendMessage(CBEM_INSERTITEM, 0, reinterpret_cast<LPARAM>(&item));
|
||||
|
||||
if (oldIndex < 0)
|
||||
DbgPrint("ERROR %d\n", GetLastError());
|
||||
}
|
||||
|
||||
fCombobox.SendMessage(CB_SETCURSEL, -1, 0);
|
||||
fCombobox.SendMessage(CB_SETCURSEL, oldIndex, 0);
|
||||
|
||||
//fAddressEditBox->SetCurrentDir(index);
|
||||
fCombobox.SendMessage(CBEM_SETITEM, 0, reinterpret_cast<LPARAM>(&item));
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -435,3 +445,150 @@ HRESULT STDMETHODCALLTYPE CAddressEditBox::GetSizeMax(ULARGE_INTEGER *pcbSize)
|
|||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
void CAddressEditBox::PopulateComboBox(LPITEMIDLIST pidlCurrent)
|
||||
{
|
||||
HRESULT hr;
|
||||
LPITEMIDLIST pidl;
|
||||
int indent = 0;
|
||||
int index;
|
||||
|
||||
index = SendMessageW(hComboBoxEx, CB_GETCOUNT, 0, 0);
|
||||
for (int i = 0; i < index; i++)
|
||||
SendMessageW(hComboBoxEx, CBEM_DELETEITEM, i, 0);
|
||||
SendMessageW(hComboBoxEx, CB_RESETCONTENT, 0, 0);
|
||||
|
||||
/* Calculate the indent level. No need to clone the pidl */
|
||||
pidl = pidlCurrent;
|
||||
do
|
||||
{
|
||||
if(!pidl->mkid.cb)
|
||||
break;
|
||||
pidl = ILGetNext(pidl);
|
||||
indent++;
|
||||
} while (pidl);
|
||||
index = indent;
|
||||
|
||||
/* Add every id from the pidl in the combo box */
|
||||
pidl = ILClone(pidlCurrent);
|
||||
do
|
||||
{
|
||||
AddComboBoxItem(pidl, 0, index);
|
||||
ILRemoveLastID(pidl);
|
||||
index--;
|
||||
} while (index >= 0);
|
||||
ILFree(pidl);
|
||||
|
||||
/* Add the items of the desktop */
|
||||
FillOneLevel(0, 1, indent);
|
||||
|
||||
/* Add the items of My Computer */
|
||||
hr = SHGetSpecialFolderLocation(0, CSIDL_DRIVES, &pidl);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return;
|
||||
|
||||
for(LPITEMIDLIST i = GetItemData(0); i; i = GetItemData(index))
|
||||
{
|
||||
if (ILIsEqual(i, pidl))
|
||||
{
|
||||
FillOneLevel(index, 2, indent);
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
ILFree(pidl);
|
||||
}
|
||||
|
||||
void CAddressEditBox::AddComboBoxItem(LPITEMIDLIST pidl, int index, int indent)
|
||||
{
|
||||
HRESULT hr;
|
||||
WCHAR buf[4096];
|
||||
|
||||
LPCITEMIDLIST pidlChild;
|
||||
CComPtr<IShellFolder> sf;
|
||||
hr = SHBindToParent(pidl, IID_PPV_ARG(IShellFolder, &sf), &pidlChild);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return;
|
||||
|
||||
STRRET strret;
|
||||
hr = sf->GetDisplayNameOf(pidlChild, SHGDN_FORADDRESSBAR, &strret);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return;
|
||||
|
||||
hr = StrRetToBufW(&strret, pidlChild, buf, 4095);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return;
|
||||
|
||||
COMBOBOXEXITEMW item = {0};
|
||||
item.mask = CBEIF_LPARAM | CBEIF_INDENT | CBEIF_SELECTEDIMAGE | CBEIF_IMAGE | CBEIF_TEXT;
|
||||
item.iImage = SHMapPIDLToSystemImageListIndex(sf, pidlChild, &item.iSelectedImage);
|
||||
item.pszText = buf;
|
||||
item.lParam = (LPARAM)(ILClone(pidl));
|
||||
item.iIndent = indent;
|
||||
item.iItem = index;
|
||||
SendMessageW(hComboBoxEx, CBEM_INSERTITEMW, 0, (LPARAM)&item);
|
||||
}
|
||||
|
||||
void CAddressEditBox::FillOneLevel(int index, int levelIndent, int indent)
|
||||
{
|
||||
HRESULT hr;
|
||||
ULONG numObj;
|
||||
int count;
|
||||
LPITEMIDLIST pidl, pidl2, pidl3, pidl4;
|
||||
|
||||
count = index + 1;
|
||||
pidl = GetItemData(index);
|
||||
pidl2 = GetItemData(count);
|
||||
if(pidl)
|
||||
{
|
||||
CComPtr<IShellFolder> psfDesktop;
|
||||
CComPtr<IShellFolder> psfItem;
|
||||
|
||||
hr = SHGetDesktopFolder(&psfDesktop);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return;
|
||||
|
||||
if (!pidl->mkid.cb)
|
||||
{
|
||||
psfItem = psfDesktop;
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = psfDesktop->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, &psfItem));
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return;
|
||||
}
|
||||
|
||||
CComPtr<IEnumIDList> pEnumIDList;
|
||||
hr = psfItem->EnumObjects(0, SHCONTF_FOLDERS | SHCONTF_INCLUDEHIDDEN, &pEnumIDList);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return;
|
||||
|
||||
do
|
||||
{
|
||||
hr = pEnumIDList->Next(1, &pidl3, &numObj);
|
||||
if(hr != S_OK || !numObj)
|
||||
break;
|
||||
|
||||
pidl4 = ILCombine(pidl, pidl3);
|
||||
if (pidl2 && ILIsEqual(pidl4, pidl2))
|
||||
count += (indent - levelIndent);
|
||||
else
|
||||
AddComboBoxItem(pidl4, count, levelIndent);
|
||||
count++;
|
||||
ILFree(pidl3);
|
||||
ILFree(pidl4);
|
||||
} while (true);
|
||||
}
|
||||
}
|
||||
|
||||
LPITEMIDLIST CAddressEditBox::GetItemData(int index)
|
||||
{
|
||||
COMBOBOXEXITEMW item;
|
||||
|
||||
memset(&item, 0, sizeof(COMBOBOXEXITEMW));
|
||||
item.mask = CBEIF_LPARAM;
|
||||
item.iItem = index;
|
||||
SendMessageW(hComboBoxEx, CBEM_GETITEMW, 0, (LPARAM)&item);
|
||||
return (LPITEMIDLIST)item.lParam;
|
||||
}
|
||||
|
|
|
@ -38,10 +38,15 @@ private:
|
|||
DWORD fAdviseCookie;
|
||||
CComPtr<IUnknown> fSite;
|
||||
LPITEMIDLIST pidlLastParsed;
|
||||
HWND hComboBoxEx;
|
||||
public:
|
||||
CAddressEditBox();
|
||||
~CAddressEditBox();
|
||||
private:
|
||||
void PopulateComboBox(LPITEMIDLIST pidl);
|
||||
void AddComboBoxItem(LPITEMIDLIST pidl, int index, int indent);
|
||||
void FillOneLevel(int index, int levelIndent, int indent);
|
||||
LPITEMIDLIST GetItemData(int index);
|
||||
public:
|
||||
// *** IShellService methods ***
|
||||
virtual HRESULT STDMETHODCALLTYPE SetOwner(IUnknown *);
|
||||
|
|
Loading…
Reference in a new issue