WINE_DEFAULT_DEBUG_CHANNEL(shell);
+#define SHV_CHANGE_NOTIFY (WM_USER + 0x1111)
+
/* original margins and control size */
typedef struct tagLAYOUT_DATA
{
LPITEMIDLIST pidlRet;
LAYOUT_DATA *layout; /* filled by LayoutInit, used by LayoutUpdate */
SIZE szMin;
+ ULONG hNotify; /* change notification handle */
} browse_info;
typedef struct tagTV_ITEMDATA
return 0;
}
+static HRESULT BrsFolder_Rename(browse_info *info, HTREEITEM rename)
+{
+ SendMessageW(info->hwndTreeView, TVM_SELECTITEM, TVGN_CARET, (LPARAM)rename);
+ SendMessageW(info->hwndTreeView, TVM_EDITLABELW, 0, (LPARAM)rename);
+ return S_OK;
+}
+
+static LRESULT BrsFolder_Treeview_Keydown(browse_info *info, LPNMTVKEYDOWN keydown)
+{
+ HTREEITEM selected_item;
+
+ /* Old dialog doesn't support those advanced features */
+ if (!(info->lpBrowseInfo->ulFlags & BIF_NEWDIALOGSTYLE))
+ return 0;
+
+ selected_item = (HTREEITEM)SendMessageW(info->hwndTreeView, TVM_GETNEXTITEM, TVGN_CARET, 0);
+
+ switch (keydown->wVKey)
+ {
+ case VK_F2:
+ BrsFolder_Rename(info, selected_item);
+ break;
+ case VK_DELETE:
+ {
+#ifdef __REACTOS__
+ /*********************************************************
+ FIXME: Add a proper alternative implementation for ReactOS
+
+ NOTES: Wine makes use of the ISFHelper interface, which we
+ don't have in ReactOS.
+ It's defined in dlls/shell32/shellfolder.h and implemented
+ in dlls/shell32/shfldr_fs.c on Wine's side.
+ *********************************************************/
+#else
+ const ITEMIDLIST *item_id;
+ ISFHelper *psfhlp;
+ HRESULT hr;
+ TVITEMW item;
+ TV_ITEMDATA *item_data;
+
+ item.mask = TVIF_PARAM;
+ item.mask = TVIF_HANDLE|TVIF_PARAM;
+ item.hItem = selected_item;
+ SendMessageW(info->hwndTreeView, TVM_GETITEMW, 0, (LPARAM)&item);
+ item_data = (TV_ITEMDATA *)item.lParam;
+ item_id = item_data->lpi;
+
+ hr = IShellFolder_QueryInterface(item_data->lpsfParent, &IID_ISFHelper, (void**)&psfhlp);
+ if(FAILED(hr))
+ return 0;
+
+ /* perform the item deletion - tree view gets updated over shell notification */
+ ISFHelper_DeleteItems(psfhlp, 1, &item_id);
+ ISFHelper_Release(psfhlp);
+#endif
+ }
+ break;
+ }
+ return 0;
+}
+
static LRESULT BrsFolder_OnNotify( browse_info *info, UINT CtlID, LPNMHDR lpnmh )
{
NMTREEVIEWW *pnmtv = (NMTREEVIEWW *)lpnmh;
case TVN_ENDLABELEDITA:
case TVN_ENDLABELEDITW:
return BrsFolder_Treeview_Rename( info, (LPNMTVDISPINFOW)pnmtv );
+
+ case TVN_KEYDOWN:
+ return BrsFolder_Treeview_Keydown( info, (LPNMTVKEYDOWN)pnmtv );
default:
WARN("unhandled (%d)\n", pnmtv->hdr.code);
static BOOL BrsFolder_OnCreate( HWND hWnd, browse_info *info )
{
+ LPITEMIDLIST computer_pidl;
+ SHChangeNotifyEntry ntreg;
LPBROWSEINFOW lpBrowseInfo = info->lpBrowseInfo;
info->hWnd = hWnd;
else
ERR("treeview control missing!\n");
+ /* Register for change notifications */
+ SHGetFolderLocation(NULL, CSIDL_DESKTOP, NULL, 0, &computer_pidl);
+
+ ntreg.pidl = computer_pidl;
+ ntreg.fRecursive = TRUE;
+
+ info->hNotify = SHChangeNotifyRegister(hWnd, SHCNRF_InterruptLevel, SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1, &ntreg);
+
browsefolder_callback( info->lpBrowseInfo, hWnd, BFFM_INITIALIZED, 0 );
return TRUE;
}
-static HRESULT BrsFolder_Rename(browse_info *info, HTREEITEM rename)
-{
- SendMessageW(info->hwndTreeView, TVM_SELECTITEM, TVGN_CARET, (LPARAM)rename);
- SendMessageW(info->hwndTreeView, TVM_EDITLABELW, 0, (LPARAM)rename);
- return S_OK;
-}
-
static HRESULT BrsFolder_NewFolder(browse_info *info)
{
DWORD flags = BrowseFlagsToSHCONTF(info->lpBrowseInfo->ulFlags);
info->layout = NULL;
}
+ SHChangeNotifyDeregister(info->hNotify);
+
return 0;
}
+/* Find a treeview node by recursively walking the treeview */
+static HTREEITEM BrsFolder_FindItemByPidl(browse_info *info, LPCITEMIDLIST pidl, HTREEITEM hItem)
+{
+ TV_ITEMW item;
+ TV_ITEMDATA *item_data;
+ HRESULT hr;
+
+ item.mask = TVIF_HANDLE | TVIF_PARAM;
+ item.hItem = hItem;
+ SendMessageW(info->hwndTreeView, TVM_GETITEMW, 0, (LPARAM)&item);
+ item_data = (TV_ITEMDATA *)item.lParam;
+
+ hr = IShellFolder_CompareIDs(item_data->lpsfParent, 0, item_data->lpifq, pidl);
+ if(SUCCEEDED(hr) && !HRESULT_CODE(hr))
+ return hItem;
+
+ hItem = (HTREEITEM)SendMessageW(info->hwndTreeView, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
+
+ while (hItem)
+ {
+ HTREEITEM newItem = BrsFolder_FindItemByPidl(info, pidl, hItem);
+ if (newItem)
+ return newItem;
+ hItem = (HTREEITEM)SendMessageW(info->hwndTreeView, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem);
+ }
+ return NULL;
+}
+
+static LRESULT BrsFolder_OnChange(browse_info *info, const LPCITEMIDLIST *pidls, LONG event)
+{
+ BOOL ret = TRUE;
+
+ TRACE("(%p)->(%p, %p, 0x%08x)\n", info, pidls[0], pidls[1], event);
+
+ switch (event)
+ {
+ case SHCNE_RMDIR:
+ case SHCNE_DELETE:
+ {
+ HTREEITEM handle_root = (HTREEITEM)SendMessageW(info->hwndTreeView, TVM_GETNEXTITEM, TVGN_ROOT, 0);
+ HTREEITEM handle_item = BrsFolder_FindItemByPidl(info, pidls[0], handle_root);
+
+ if (handle_item)
+ SendMessageW(info->hwndTreeView, TVM_DELETEITEM, 0, (LPARAM)handle_item);
+
+ break;
+ }
+ }
+ return ret;
+}
+
/*************************************************************************
* BrsFolderDlgProc32 (not an exported API function)
*/
case BFFM_SETEXPANDED: /* unicode only */
return BrsFolder_OnSetExpanded(info, (LPVOID)lParam, (BOOL)wParam, NULL);
+ case SHV_CHANGE_NOTIFY:
+ return BrsFolder_OnChange(info, (const LPCITEMIDLIST*)wParam, (LONG)lParam);
+
case WM_DESTROY:
return BrsFolder_OnDestroy(info);
}