* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
- * FIXME: The order by part of the background context menu should be
- * built according to the columns shown.
- *
* FIXME: CheckToolbar: handle the "new folder" and "folder up" button
*/
/*
TODO:
- Load/Save the view state from/into the stream provided by the ShellBrowser.
-- Code to merge menus in the shellbrowser is incorrect.
-- Move the background context menu creation into shell view. It should store the
- shell view HWND to send commands.
-- Shell view should do SetCommandTarget on internet toolbar.
- When editing starts on item, set edit text to for editing value.
-- When shell view is called back for item info, let listview save the value.
- Fix shell view to handle view mode popup exec.
- The background context menu should have a pidl just like foreground menus. This
causes crashes when dynamic handlers try to use the NULL pidl.
-- The SHELLDLL_DefView should not be filled with blue unconditionally. This causes
- annoying flashing of blue even on XP, and is not correct.
- Reorder of columns doesn't work - might be bug in comctl32
*/
LONG m_iDragOverItem; /* Dragged over item's index, iff m_pCurDropTarget != NULL */
UINT m_cScrollDelay; /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */
POINT m_ptLastMousePos; /* Mouse position at last DragOver call */
+ POINT m_ptFirstMousePos; /* Mouse position when the drag operation started */
//
CComPtr<IContextMenu> m_pCM;
if (GetKeyState(VK_CONTROL) & 0x8000)
cmi.fMask |= CMIC_MASK_CONTROL_DOWN;
- return m_pCM->InvokeCommand(&cmi);
+ HRESULT hr = m_pCM->InvokeCommand(&cmi);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+ return S_OK;
}
/**********************************************************
return E_FAIL;
hResult = GetItemObject(SVGIO_SELECTION, IID_PPV_ARG(IContextMenu, &m_pCM));
- if (FAILED(hResult))
+ if (FAILED_UNEXPECTEDLY(hResult))
goto cleanup;
IUnknown_SetSite(m_pCM, (IShellView *)this);
hResult = m_pCM->QueryContextMenu(hMenu, 0, 0x20, 0x7fff, CMF_DEFAULTONLY);
- if (FAILED(hResult))
+ if (FAILED_UNEXPECTEDLY(hResult))
goto cleanup;
uCommand = GetMenuDefaultItem(hMenu, FALSE, 0);
m_cidl = m_ListView.GetSelectedCount();
hResult = GetItemObject( m_cidl ? SVGIO_SELECTION : SVGIO_BACKGROUND, IID_PPV_ARG(IContextMenu, &m_pCM));
- if (FAILED( hResult))
+ if (FAILED_UNEXPECTEDLY(hResult))
goto cleanup;
IUnknown_SetSite(m_pCM, (IShellView *)this);
hResult = m_pCM->QueryContextMenu(m_hContextMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL);
- if (FAILED( hResult))
+ if (FAILED_UNEXPECTEDLY(hResult))
goto cleanup;
uCommand = TrackPopupMenu(m_hContextMenu,
return 0;
hResult = GetItemObject( bUseSelection ? SVGIO_SELECTION : SVGIO_BACKGROUND, IID_PPV_ARG(IContextMenu, &m_pCM));
- if (FAILED( hResult))
+ if (FAILED_UNEXPECTEDLY( hResult))
goto cleanup;
IUnknown_SetSite(m_pCM, (IShellView *)this);
hResult = m_pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL);
- if (FAILED( hResult))
+ if (FAILED_UNEXPECTEDLY( hResult))
goto cleanup;
InvokeContextMenuCommand(uCommand);
if (m_pSF2Parent)
{
SHELLDETAILS sd;
- if (FAILED(m_pSF2Parent->GetDetailsOf(pidl, lpdi->item.iSubItem, &sd)))
- {
- FIXME("failed to get details\n");
+ if (FAILED_UNEXPECTEDLY(m_pSF2Parent->GetDetailsOf(pidl, lpdi->item.iSubItem, &sd)))
break;
- }
if (lpnmh->code == LVN_GETDISPINFOA)
{
DWORD dwEffect2;
m_pSourceDataObject = pda;
+ m_ptFirstMousePos = ((LPNMLISTVIEW)lParam)->ptAction;
+ ClientToScreen(&m_ptFirstMousePos);
DoDragDrop(pda, this, dwEffect, &dwEffect2);
case SVGIO_BACKGROUND:
if (IsEqualIID(riid, IID_IContextMenu))
{
- //*ppvOut = ISvBgCm_Constructor(m_pSFParent, FALSE);
if (!ppvOut)
hr = E_OUTOFMEMORY;
- IContextMenu* pcm;
- hr = CDefFolderMenu_Create2(NULL, NULL, 0, NULL, m_pSFParent, NULL, 0, NULL, &pcm);
- if (FAILED(hr))
+ hr = CDefViewBckgrndMenu_CreateInstance(m_pSF2Parent, riid, ppvOut);
+ if (FAILED_UNEXPECTEDLY(hr))
return hr;
- *ppvOut = pcm;
+
}
else if (IsEqualIID(riid, IID_IDispatch))
{
{
hr = CDefViewDual_Constructor(riid, (LPVOID*)&m_pShellFolderViewDual);
if (FAILED_UNEXPECTEDLY(hr))
- {
return hr;
- }
}
hr = m_pShellFolderViewDual->QueryInterface(riid, ppvOut);
}
case SVGIO_SELECTION:
GetSelections();
hr = m_pSFParent->GetUIObjectOf(m_hWnd, m_cidl, m_apidl, riid, 0, ppvOut);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
break;
}
m_ListView.SetItemState(iItem, lvItem.state, lvItem.stateMask);
- if (dwFlags & SVSI_EDIT)
+ if ((dwFlags & SVSI_EDIT) == SVSI_EDIT)
m_ListView.EditLabel(iItem);
return S_OK;
HRESULT CDefView::drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
{
- LVHITTESTINFO htinfo;
LONG lResult;
HRESULT hr;
RECT clientRect;
/* Map from global to client coordinates and query the index of the listview-item, which is
* currently under the mouse cursor. */
- htinfo.pt.x = pt.x;
- htinfo.pt.y = pt.y;
- htinfo.flags = LVHT_ONITEM;
- ::ScreenToClient(m_ListView, &htinfo.pt);
+ LVHITTESTINFO htinfo { {pt.x, pt.y}, LVHT_ONITEM};
+ ScreenToClient(&htinfo.pt);
lResult = m_ListView.HitTest(&htinfo);
/* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
m_ptLastMousePos = htinfo.pt;
+ /* We need to check if we drag the selection over itself */
+ if (lResult != -1 && m_pSourceDataObject.p != NULL)
+ {
+ PCUITEMID_CHILD pidl = _PidlByItem(lResult);
+
+ for (UINT i = 0; i < m_cidl; i++)
+ {
+ if (pidl == m_apidl[i])
+ {
+ /* The item that is being draged is hovering itself. */
+ lResult = -1;
+ break;
+ }
+ }
+ }
+
/* If we are still over the previous sub-item, notify it via DragOver and return. */
if (m_pCurDropTarget && lResult == m_iDragOverItem)
return m_pCurDropTarget->DragOver(grfKeyState, pt, pdwEffect);
/* We've left the previous sub-item, notify it via DragLeave and Release it. */
if (m_pCurDropTarget)
{
+ PCUITEMID_CHILD pidl = _PidlByItem(m_iDragOverItem);
+ if (pidl)
+ SelectItem(pidl, 0);
+
m_pCurDropTarget->DragLeave();
m_pCurDropTarget.Release();
}
m_iDragOverItem = lResult;
+
if (lResult == -1)
{
/* We are not above one of the listview's subitems. Bind to the parent folder's
return hr;
/* Notify the item just entered via DragEnter. */
- return m_pCurDropTarget->DragEnter(m_pCurDataObject, grfKeyState, pt, pdwEffect);
+ hr = m_pCurDropTarget->DragEnter(m_pCurDataObject, grfKeyState, pt, pdwEffect);
+
+ if (m_iDragOverItem != -1 && pdwEffect != DROPEFFECT_NONE)
+ {
+ SelectItem(m_iDragOverItem, SVSI_SELECT);
+ }
+
+ return hr;
}
HRESULT WINAPI CDefView::DragEnter(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
{
/* Get a hold on the data object for later calls to DragEnter on the sub-folders */
m_pCurDataObject = pDataObject;
- pDataObject->AddRef();
return drag_notify_subitem(grfKeyState, pt, pdwEffect);
}
{
ERR("GetKeyState(VK_LBUTTON): %d\n", GetKeyState(VK_LBUTTON));
- if ((m_iDragOverItem == -1) &&
+ if ((m_iDragOverItem == -1 || m_pCurDropTarget == NULL) &&
(*pdwEffect & DROPEFFECT_MOVE) &&
- (GetKeyState(VK_LBUTTON) != 0) &&
+ /*(GetKeyState(VK_LBUTTON) != 0) &&*/
(m_pSourceDataObject.p) &&
(SHIsSameObject(pDataObject, m_pSourceDataObject)))
{
- ERR("Should implement moving items here!\n");
-
if (m_pCurDropTarget)
{
m_pCurDropTarget->DragLeave();
m_pCurDropTarget.Release();
}
+
+ /* Restore the selection */
+ m_ListView.SetItemState(-1, 0, LVIS_SELECTED);
+ for (UINT i = 0 ; i < m_cidl; i++)
+ SelectItem(m_apidl[i], SVSI_SELECT);
+
+ /* Reposition the items */
+ int lvIndex = -1;
+ while ((lvIndex = m_ListView.GetNextItem(lvIndex, LVNI_SELECTED)) > -1)
+ {
+ POINT ptItem;
+ if (m_ListView.GetItemPosition(lvIndex, &ptItem))
+ {
+ ptItem.x += pt.x - m_ptFirstMousePos.x;
+ ptItem.y += pt.y - m_ptFirstMousePos.y;
+ m_ListView.SetItemPosition(lvIndex, &ptItem);
+ }
+ }
}
else if (m_pCurDropTarget)
{