Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

800 lines
30 KiB

  1. //
  2. // Win32 window that hosts a pane on the desktop.
  3. //
  4. // You are expected to derive from this class and implement the virtual
  5. // methods.
  6. //
  7. #ifndef __SFTHOST_H__
  8. #define __SFTHOST_H__
  9. #include "uemapp.h"
  10. #include "runtask.h"
  11. #include "hostutil.h"
  12. #include "dobjutil.h"
  13. //****************************************************************************
  14. //
  15. // Miscellaneous helper functions
  16. //
  17. STDAPI_(HFONT) LoadControlFont(HTHEME hTheme, int iPart, BOOL fUnderline, DWORD dwSizePercentage);
  18. STDAPI_(HRESULT)
  19. IDataObject_DragQueryFile(IDataObject *pdto, UINT iFile, LPTSTR pszBuf, UINT cch, UINT *puFiles);
  20. STDAPI_(LPITEMIDLIST)
  21. ConvertToLogIL(LPITEMIDLIST pidl);
  22. LRESULT _SendNotify(HWND hwndFrom, UINT code, OPTIONAL NMHDR *pnm = NULL);
  23. BOOL GetFileCreationTime(LPCTSTR pszFile, LPFILETIME pftCreate);
  24. /* Simple wrapper - the string needs to be freed with SHFree */
  25. LPTSTR _DisplayNameOf(IShellFolder *psf, LPCITEMIDLIST pidl, UINT shgno);
  26. HICON _IconOf(IShellFolder *psf, LPCITEMIDLIST pidl, int cxIcon);
  27. BOOL ShowInfoTip();
  28. //****************************************************************************
  29. // The base class uses the following properties in the initializing
  30. // property bag:
  31. //
  32. //
  33. // "type" - type of host to use (see HOSTTYPE array)
  34. // "asyncEnum" - 1 = enumerate in background; 0 = foreground
  35. // "iconSize" - 0 = small, 1 = large
  36. // "horizontal" - 0 = vertical (default), n = horizontal
  37. // n = number of items to show
  38. class PaneItem;
  39. class PaneItem
  40. {
  41. public:
  42. PaneItem() : _iPos(-1), _iPinPos(PINPOS_UNPINNED) {}
  43. virtual ~PaneItem() { SHFree(_pszAccelerator); }
  44. static int CALLBACK DPAEnumCallback(PaneItem *self, LPVOID pData)
  45. { delete self; return TRUE; }
  46. BOOL IsPinned() const { return _iPinPos >= 0; }
  47. BOOL IsSeparator() const { return _iPinPos == PINPOS_SEPARATOR; }
  48. BOOL GetPinPos() const { return _iPinPos; }
  49. BOOL IsCascade() const { return _dwFlags & ITEMFLAG_CASCADE; }
  50. void EnableCascade() { _dwFlags |= ITEMFLAG_CASCADE; }
  51. BOOL HasSubtitle() const { return _dwFlags & ITEMFLAG_SUBTITLE; }
  52. void EnableSubtitle() { _dwFlags |= ITEMFLAG_SUBTITLE; }
  53. BOOL IsDropTarget() const { return _dwFlags & ITEMFLAG_DROPTARGET; }
  54. void EnableDropTarget() { _dwFlags |= ITEMFLAG_DROPTARGET; }
  55. BOOL HasAccelerator() { return _pszAccelerator != NULL; }
  56. virtual BOOL IsEqual(PaneItem *pItem) const { return FALSE; }
  57. enum {
  58. PINPOS_UNPINNED = -1,
  59. PINPOS_SEPARATOR = -2,
  60. };
  61. enum {
  62. ITEMFLAG_CASCADE = 0x0001,
  63. ITEMFLAG_SUBTITLE = 0x0002,
  64. ITEMFLAG_DROPTARGET = 0x0004,
  65. };
  66. private:
  67. friend class SFTBarHost;
  68. int _iPos; /* Position on screen (or garbage if not on screen) */
  69. public:
  70. int _iPinPos; /* Pin position (or special PINPOS value) */
  71. DWORD _dwFlags; /* ITEMFLAG_* values */
  72. LPTSTR _pszAccelerator;/* Text with ampersand (for keyboard accelerator) */
  73. };
  74. //
  75. // Note: Since this is a base class, we can't use ATL because the base
  76. // class's CreateInstance won't know how to construct the derived classes.
  77. //
  78. class SFTBarHost
  79. : public IDropTarget
  80. , public IDropSource
  81. , public CAccessible
  82. {
  83. public:
  84. static BOOL Register();
  85. static BOOL Unregister();
  86. // Would normally be "protected" except that proglist.cpp actually implements
  87. // in a separate class and forwards.
  88. public:
  89. /*
  90. * Classes which derive from this class are expected to implement
  91. * the following methods.
  92. */
  93. /* Constructor with return code */
  94. virtual HRESULT Initialize() PURE;
  95. /* Destructor */
  96. virtual ~SFTBarHost();
  97. /* Enumerate the objects and call AddItem for each one you find */
  98. // TODO: Maybe the EnumItems should be moved to a background thread
  99. virtual void EnumItems() PURE;
  100. virtual BOOL NeedBackgroundEnum() { return FALSE; }
  101. virtual BOOL HasDynamicContent() { return FALSE; }
  102. /* Compare two objects, tell me which one should come first */
  103. virtual int CompareItems(PaneItem *p1, PaneItem *p2) PURE;
  104. /*
  105. * Given a PaneItem, produce the pidl and IShellFolder associated with it.
  106. * The IShellFolder will be Release()d when no longer needed.
  107. */
  108. virtual HRESULT GetFolderAndPidl(PaneItem *pitem, IShellFolder **ppsfOut, LPCITEMIDLIST *ppidlOut) PURE;
  109. // An over-ridable method to add an image to our private imagelist for an item (virtual but not pure)
  110. virtual int AddImageForItem(PaneItem *pitem, IShellFolder *psf, LPCITEMIDLIST pidl, int iPos);
  111. /*
  112. * Dispatch a shell notification. Default handler ignores.
  113. */
  114. virtual void OnChangeNotify(UINT id, LONG lEvent, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) { }
  115. /*
  116. * Allows derived classes to control their own icon size.
  117. */
  118. enum ICONSIZE {
  119. ICONSIZE_SMALL, // typically 16x16
  120. ICONSIZE_LARGE, // typically 32x32
  121. ICONSIZE_MEDIUM, // typically 24x24
  122. };
  123. virtual int ReadIconSize() PURE;
  124. /*
  125. * Optional hook into window procedure.
  126. *
  127. * Default behavior is just to call DefWindowProc.
  128. */
  129. virtual LRESULT OnWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  130. {
  131. return ::DefWindowProc(hwnd, uMsg, wParam, lParam);
  132. }
  133. /*
  134. * Required if AdjustDeleteMenuItem is customized.
  135. * Invoked when a context menu command is invoked.
  136. * Host must intercept the
  137. * "delete" command. Other commands can also be intercepted as
  138. * necessary.
  139. */
  140. virtual HRESULT ContextMenuInvokeItem(PaneItem *pitem, IContextMenu *pcm, CMINVOKECOMMANDINFOEX *pici, LPCTSTR pszVerb);
  141. /*
  142. * Required if HOSTF_CANRENAME is passed: Invoked when an item
  143. * is renamed.
  144. *
  145. * Note: The client is allowed to change the pidl associated with an
  146. * item during a rename. (In fact, it's expected to!) So callers
  147. * which have called GetFolderAndPidl need to call it again after the
  148. * rename to get the correct post-rename pidl.
  149. */
  150. virtual HRESULT ContextMenuRenameItem(PaneItem *pitem, LPCTSTR ptszNewName) { return E_NOTIMPL; }
  151. /*
  152. * Optional hook for obtaining the display name of an item.
  153. * The default implementation calls IShellFolder::GetDisplayNameOf.
  154. * If hooked, the returned string should be allocated by SHAlloc().
  155. */
  156. virtual LPTSTR DisplayNameOfItem(PaneItem *pitem, IShellFolder *psf, LPCITEMIDLIST pidlItem, SHGNO shgno)
  157. {
  158. return _DisplayNameOf(psf, pidlItem, shgno);
  159. }
  160. /*
  161. * Required if pinnned items are created. Invoked when the user moves
  162. * a pinned item.
  163. */
  164. virtual HRESULT MovePinnedItem(PaneItem *pitem, int iInsert) { return E_NOTIMPL; }
  165. /*
  166. * Optional hook into the SMN_INITIALUPDATE notification.
  167. */
  168. virtual void PrePopulate() { }
  169. /*
  170. * Optional handler that says whether an item is still valid.
  171. */
  172. virtual BOOL IsItemStillValid(PaneItem *pitem) { return TRUE; }
  173. /*
  174. * Required if HOSTF_CASCADEMENU. Invoked when user wants to view
  175. * a cascaded menu.
  176. */
  177. virtual HRESULT GetCascadeMenu(PaneItem *pitem, IShellMenu **ppsm) { return E_FAIL; }
  178. /*
  179. * Required if any items have subtitles. Returns the subtitle of the item.
  180. */
  181. virtual LPTSTR SubtitleOfItem(PaneItem *pitem, IShellFolder *psf, LPCITEMIDLIST pidlItem) { return NULL; }
  182. /*
  183. * Optionally over-ridable method to ge the infotip for an item. Default does a GetFolderAndPidl/GetInfoTip.
  184. */
  185. virtual void GetItemInfoTip(PaneItem *pitem, LPTSTR pszText, DWORD cch);
  186. /*
  187. * Specify whether the data object can be inserted into the pin list.
  188. * (Default: No.)
  189. */
  190. virtual BOOL IsInsertable(IDataObject *pdto) { return FALSE; }
  191. /*
  192. * If you say that something is insertable, they you may be asked to
  193. * insert it.
  194. */
  195. virtual HRESULT InsertPinnedItem(IDataObject *pdto, int iInsert)
  196. {
  197. ASSERT(FALSE); // You must implement this if you implement IsInsertable
  198. return E_FAIL;
  199. }
  200. /*
  201. * An over-ridable method to allow hooking into keyboard accelerators.
  202. */
  203. virtual TCHAR GetItemAccelerator(PaneItem *pitem, int iItemStart);
  204. /*
  205. * Specify whether the item should be displayed as bold.
  206. * Default is to boldface if pinned.
  207. */
  208. virtual BOOL IsBold(PaneItem *pitem) { return pitem->IsPinned(); }
  209. /*
  210. * Notify the client that a system imagelist index has changed.
  211. * Default is to re-extract icons for any matching listview items.
  212. */
  213. virtual void UpdateImage(int iImage);
  214. /*
  215. * Optional method to allow clients to specify how "Delete"
  216. * should be exposed (if at all). Return 0 to disallow "Delete".
  217. * Return the string ID of the string to show for the command.
  218. * Set *puiFlags to any additional flags to pass to ModifyMenu.
  219. * Default is to disallow delete.
  220. */
  221. virtual UINT AdjustDeleteMenuItem(PaneItem *pitem, UINT *puiFlags) { return 0; }
  222. /*
  223. * Allow client to reject/over-ride the IContextMenu on a per-item basis
  224. */
  225. virtual HRESULT _GetUIObjectOfItem(PaneItem *pitem, REFIID riid, LPVOID *ppv);
  226. protected:
  227. /*
  228. * Classes which derive from this class may call the following
  229. * helper methods.
  230. */
  231. /*
  232. * Add a PaneItem to the list - if add fails, item will be delete'd.
  233. *
  234. * CLEANUP psf must be NULL; pidl must be the absolute pidl to the item
  235. * being added. Leftover from dead HOSTF_PINITEMSBYFOLDER feature.
  236. * Needs to be cleaned up.
  237. *
  238. * Passing psf and pidlChild are for perf.
  239. */
  240. BOOL AddItem(PaneItem *pitem, IShellFolder *psf, LPCITEMIDLIST pidlChild);
  241. /*
  242. * Use AddImage when you already have a HICON that needs to go to the private image list.
  243. */
  244. int AddImage(HICON hIcon);
  245. /*
  246. * Hooking into change notifications
  247. */
  248. enum {
  249. SFTHOST_MAXCLIENTNOTIFY = 7, // Clients get this many notifications
  250. SFTHOST_MAXHOSTNOTIFY = 1, // We use this many ourselves
  251. SFTHOST_HOSTNOTIFY_UPDATEIMAGE = SFTHOST_MAXCLIENTNOTIFY,
  252. SFTHOST_MAXNOTIFY = SFTHOST_MAXCLIENTNOTIFY + SFTHOST_MAXHOSTNOTIFY,
  253. };
  254. BOOL RegisterNotify(UINT id, LONG lEvents, LPCITEMIDLIST pidl, BOOL fRecursive)
  255. {
  256. ASSERT(id < SFTHOST_MAXCLIENTNOTIFY);
  257. return _RegisterNotify(id, lEvents, pidl, fRecursive);
  258. }
  259. BOOL UnregisterNotify(UINT id);
  260. /*
  261. * Forcing a re-enumeration.
  262. */
  263. void Invalidate() { _fEnumValid = FALSE; }
  264. /*
  265. * Informing host of desired size.
  266. */
  267. void SetDesiredSize(int cPinned, int cNormal)
  268. {
  269. _cPinnedDesired = cPinned;
  270. _cNormalDesired = cNormal;
  271. }
  272. BOOL AreNonPinnedItemsDesired()
  273. {
  274. return _cNormalDesired;
  275. }
  276. void StartRefreshTimer() { SetTimer(_hwnd, IDT_REFRESH, 5000, NULL); }
  277. void ForceChange() { _fForceChange = TRUE; }
  278. protected:
  279. /*
  280. * The constructor must be marked "protected" so people can derive
  281. * from us.
  282. */
  283. enum {
  284. HOSTF_FIREUEMEVENTS = 0x00000001,
  285. HOSTF_CANDELETE = 0x00000002,
  286. HOSTF_Unused = 0x00000004, // recycle me!
  287. HOSTF_CANRENAME = 0x00000008,
  288. HOSTF_REVALIDATE = 0x00000010,
  289. HOSTF_RELOADTEXT = 0x00000020, // requires HOSTF_REVALIDATE
  290. HOSTF_CASCADEMENU = 0x00000040,
  291. };
  292. SFTBarHost(DWORD dwFlags = 0)
  293. : _dwFlags(dwFlags)
  294. , _lRef(1)
  295. , _iInsert(-1)
  296. , _clrBG(CLR_INVALID)
  297. , _iCascading(-1)
  298. {
  299. }
  300. enum {
  301. SFTBM_REPOPULATE = WM_USER,
  302. SFTBM_CHANGENOTIFY,
  303. SFTBM_REFRESH = SFTBM_CHANGENOTIFY + SFTHOST_MAXNOTIFY,
  304. SFTBM_CASCADE,
  305. SFTBM_ICONUPDATE,
  306. };
  307. public:
  308. /*
  309. * Interface stuff...
  310. */
  311. // *** IUnknown ***
  312. STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppvOut);
  313. STDMETHODIMP_(ULONG) AddRef();
  314. STDMETHODIMP_(ULONG) Release();
  315. // *** IDropTarget ***
  316. STDMETHODIMP DragEnter(IDataObject *pdto, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
  317. STDMETHODIMP DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
  318. STDMETHODIMP DragLeave();
  319. STDMETHODIMP Drop(IDataObject *pdto, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
  320. // *** IDropSource ***
  321. STDMETHODIMP GiveFeedback(DWORD dwEffect);
  322. STDMETHODIMP QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState);
  323. // *** IAccessible overridden methods ***
  324. STDMETHODIMP get_accRole(VARIANT varChild, VARIANT *pvarRole);
  325. STDMETHODIMP get_accState(VARIANT varChild, VARIANT *pvarState);
  326. STDMETHODIMP get_accKeyboardShortcut(VARIANT varChild, BSTR *pszKeyboardShortcut);
  327. STDMETHODIMP get_accDefaultAction(VARIANT varChild, BSTR *pszDefAction);
  328. STDMETHODIMP accDoDefaultAction(VARIANT varChild);
  329. // Helpers
  330. //
  331. // It is pointless to move an object to a place adjacent to itself,
  332. // because the end result is that nothing happens.
  333. //
  334. inline IsInsertMarkPointless(int iInsert)
  335. {
  336. return _fDragToSelf &&
  337. IsInRange(iInsert, _iPosDragOut, _iPosDragOut + 1);
  338. }
  339. void _PurgeDragDropData();
  340. HRESULT _DragEnter(IDataObject *pdto, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
  341. HRESULT _TryInnerDropTarget(int iItem, DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect);
  342. void _ClearInnerDropTarget();
  343. void _SetDragOver(int iItem);
  344. // Insert mark stuff
  345. void _SetInsertMarkPosition(int iInsert);
  346. void _InvalidateInsertMark();
  347. BOOL _GetInsertMarkRect(LPRECT prc);
  348. BOOL _IsInsertionMarkActive() { return _iInsert >= 0; }
  349. void _DrawInsertionMark(LPNMLVCUSTOMDRAW plvcd);
  350. /*
  351. * End of drag/drop stuff...
  352. */
  353. private:
  354. /*
  355. * Background enumeration stuff...
  356. */
  357. class CBGEnum : public CRunnableTask {
  358. public:
  359. CBGEnum(SFTBarHost *phost, BOOL fUrgent)
  360. : CRunnableTask(RTF_DEFAULT)
  361. , _fUrgent(fUrgent)
  362. , _phost(phost) { phost->AddRef(); }
  363. ~CBGEnum()
  364. {
  365. // We should not be the last release or else we are going to deadlock here, when _phost
  366. // tries to release the scheduler
  367. ASSERT(_phost->_lRef > 1);
  368. _phost->Release();
  369. }
  370. STDMETHODIMP RunInitRT()
  371. {
  372. _phost->_EnumerateContentsBackground();
  373. if (_phost->_hwnd) PostMessage(_phost->_hwnd, SFTBM_REPOPULATE, _fUrgent, 0);
  374. return S_OK;
  375. }
  376. private:
  377. SFTBarHost *_phost;
  378. BOOL _fUrgent;
  379. };
  380. friend class SFTBarHost::CBGEnum;
  381. private:
  382. /* Window procedure helpers */
  383. static LRESULT CALLBACK _WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  384. static LRESULT _OnNcCreate(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  385. LRESULT _OnCreate(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  386. LRESULT _OnDestroy(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  387. LRESULT _OnNcDestroy(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  388. LRESULT _OnNotify(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  389. LRESULT _OnSize(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  390. LRESULT _OnContextMenu(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  391. LRESULT _OnCtlColorStatic(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  392. LRESULT _OnMenuMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  393. LRESULT _OnEraseBackground(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  394. LRESULT _OnTimer(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  395. LRESULT _OnSetFocus(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  396. LRESULT _OnSysColorChange(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  397. LRESULT _OnForwardMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  398. LRESULT _OnUpdateUIState(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  399. LRESULT _OnRepopulate(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  400. LRESULT _OnChangeNotify(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  401. LRESULT _OnRefresh(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  402. LRESULT _OnCascade(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  403. LRESULT _OnIconUpdate(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  404. LRESULT _OnLVCustomDraw(LPNMLVCUSTOMDRAW plvcd);
  405. LRESULT _OnLVNItemActivate(LPNMITEMACTIVATE pnmia);
  406. LRESULT _OnLVNGetInfoTip(LPNMLVGETINFOTIP plvn);
  407. LRESULT _OnLVNGetEmptyText(NMLVDISPINFO *plvdi);
  408. LRESULT _OnLVNBeginDrag(LPNMLISTVIEW plv);
  409. LRESULT _OnLVNBeginLabelEdit(NMLVDISPINFO *pldvi);
  410. LRESULT _OnLVNEndLabelEdit(NMLVDISPINFO *pldvi);
  411. LRESULT _OnLVNKeyDown(LPNMLVKEYDOWN pkd);
  412. LRESULT _OnSMNGetMinSize(PSMNGETMINSIZE pgms);
  413. LRESULT _OnSMNFindItem(PSMNDIALOGMESSAGE pdm);
  414. LRESULT _OnSMNFindItemWorker(PSMNDIALOGMESSAGE pdm);
  415. LRESULT _OnSMNDismiss();
  416. LRESULT _OnHover();
  417. /* Custom draw helpers */
  418. LRESULT _OnLVPrePaint(LPNMLVCUSTOMDRAW plvcd);
  419. LRESULT _OnLVItemPrePaint(LPNMLVCUSTOMDRAW plvcd);
  420. LRESULT _OnLVSubItemPrePaint(LPNMLVCUSTOMDRAW plvcd);
  421. LRESULT _OnLVItemPostPaint(LPNMLVCUSTOMDRAW plvcd);
  422. LRESULT _OnLVPostPaint(LPNMLVCUSTOMDRAW plvcd);
  423. /* Custom draw push/pop */
  424. void _CustomDrawPush(BOOL fReal);
  425. BOOL _IsRealCustomDraw();
  426. void _CustomDrawPop();
  427. static LRESULT CALLBACK s_DropTargetSubclassProc(
  428. HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
  429. UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
  430. /* Other helpers */
  431. void _SetMaxShow(int cx, int cy);
  432. void _EnumerateContents(BOOL fUrgent);
  433. void _EnumerateContentsBackground();
  434. void _RevalidateItems();
  435. void _RevalidatePostPopup();
  436. void _ReloadText();
  437. static int CALLBACK _SortItemsAfterEnum(PaneItem *p1, PaneItem *p2, SFTBarHost *self);
  438. void _RepopulateList();
  439. void _InternalRepopulateList();
  440. int _InsertListViewItem(int iPos, PaneItem *pitem);
  441. void _ComputeListViewItemPosition(int iItem, POINT *pptOut);
  442. int _AppendEnumPaneItem(PaneItem *pitem);
  443. void _RepositionItems();
  444. void _ComputeTileMetrics();
  445. void _SetTileWidth(int cxTile);
  446. BOOL _CreateMarlett();
  447. void _CreateBoldFont();
  448. int _GetLVCurSel() {
  449. return ListView_GetNextItem(_hwndList, -1, LVNI_FOCUSED);
  450. }
  451. BOOL _OnCascade(int iItem, DWORD dwFlags);
  452. BOOL _IsPrivateImageList() const { return _iconsize == ICONSIZE_MEDIUM; }
  453. BOOL _CanHaveSubtitles() const { return _iconsize == ICONSIZE_LARGE; }
  454. int _ExtractImageForItem(PaneItem *pitem, IShellFolder *psf, LPCITEMIDLIST pidl);
  455. void _ClearListView();
  456. void _EditLabel(int iItem);
  457. BOOL _RegisterNotify(UINT id, LONG lEvents, LPCITEMIDLIST pidl, BOOL fRecursive);
  458. void _OnUpdateImage(LPCITEMIDLIST pidl, LPCITEMIDLIST pidlExtra);
  459. /* Returns E_FAIL for separators; otherwise calls client */
  460. HRESULT _GetFolderAndPidl(PaneItem *pitem, IShellFolder **ppsfOut, LPCITEMIDLIST *ppidlOut);
  461. /* Simple wrappers - the string needs to be freed with SHFree */
  462. LPTSTR _DisplayNameOfItem(PaneItem *pitem, UINT shgno);
  463. HRESULT _GetUIObjectOfItem(int iItem, REFIID riid, LPVOID *ppv);
  464. inline PaneItem *_GetItemFromLVLParam(LPARAM lParam)
  465. { return reinterpret_cast<PaneItem*>(lParam); }
  466. PaneItem *_GetItemFromLV(int iItem);
  467. enum {
  468. AIF_KEYBOARD = 1,
  469. };
  470. int _ContextMenuCoordsToItem(LPARAM lParam, POINT *pptOut);
  471. LRESULT _ActivateItem(int iItem, DWORD dwFlags); // AIF_* values
  472. HRESULT _InvokeDefaultCommand(int iItem, IShellFolder *psf, LPCITEMIDLIST pidl);
  473. void _OfferDeleteBrokenItem(PaneItem *pitem, IShellFolder *psf, LPCITEMIDLIST pidl);
  474. // If you hover the mouse for this much time, we will open it if it
  475. // cascades. This is the same value that USER uses for auto-cascading
  476. // menus.
  477. DWORD _GetCascadeHoverTime() { return GetDoubleClickTime() * 4 / 5; }
  478. static void CALLBACK SetIconAsync(LPCITEMIDLIST pidl, LPVOID pvData, LPVOID pvHint, INT iIconIndex, INT iOpenIconIndex);
  479. /*
  480. * Custom commands we add to the context menu.
  481. */
  482. enum {
  483. IDM_REMOVEFROMLIST = 1,
  484. // Insert private menu items here
  485. // range used for client QueryContextMenu
  486. IDM_QCM_MIN = 0x0100,
  487. IDM_QCM_MAX = 0x7000,
  488. };
  489. /*
  490. * Timer IDs
  491. */
  492. enum {
  493. IDT_ASYNCENUM = 1,
  494. IDT_RELOADTEXT = 2,
  495. IDT_REFRESH = 3,
  496. };
  497. /*
  498. * Miscellaneous settings.
  499. */
  500. enum {
  501. MAX_SEPARATORS = 3, /* Maximum number of separators allowed */
  502. };
  503. /*
  504. * Pinning helpers...
  505. */
  506. BOOL NeedSeparator() const { return _cPinned; }
  507. BOOL _HasSeparators() const { return _rgiSep[0] >= 0; }
  508. void _DrawSeparator(HDC hdc, int x, int y);
  509. void _DrawSeparators(LPNMLVCUSTOMDRAW plvcd);
  510. /*
  511. * Bookkeeping.
  512. */
  513. int _PosToItemNo(int iPos);
  514. int _ItemNoToPos(int iItem);
  515. /*
  516. * Accessibility helpers...
  517. */
  518. PaneItem *_GetItemFromAccessibility(const VARIANT& varChild);
  519. /*
  520. * Debugging helpers...
  521. */
  522. #if defined(DEBUG) && defined(FULL_DEBUG)
  523. void _DebugConsistencyCheck();
  524. #else
  525. inline void _DebugConsistencyCheck() { }
  526. #endif
  527. BOOL _AreChangesRestricted()
  528. {
  529. return (IsRestrictedOrUserSetting(HKEY_CURRENT_USER, REST_NOCHANGESTARMENU, TEXT("Advanced"), TEXT("Start_EnableDragDrop"), ROUS_DEFAULTALLOW | ROUS_KEYALLOWS));
  530. }
  531. protected:
  532. HTHEME _hTheme; // theme handle, can be NULL
  533. int _iThemePart; // SPP_PROGLIST SPP_PLACESLIST
  534. int _iThemePartSep; // theme part for the separator
  535. HWND _hwnd; /* Our window handle */
  536. HIMAGELIST _himl; // Imagelist handle
  537. int _cxIcon; /* Icon size for imagelist */
  538. int _cyIcon; /* Icon size for imagelist */
  539. ICONSIZE _iconsize; /* ICONSIZE_* value */
  540. private:
  541. HWND _hwndList; /* Handle of inner listview */
  542. MARGINS _margins; // margins for children (listview and oobe static) valid in theme and non-theme case
  543. int _cPinned; /* Number of those items that are pinned */
  544. DWORD _dwFlags; /* Misc flags that derived classes can set */
  545. // _dpaEnum is the DPA of enumerated items, sorted in the
  546. // _SortItemsAfterEnum sense, which prepares them for _RepopulateList.
  547. // When _dpaEnum is destroyed, its pointers must be delete'd.
  548. CDPA<PaneItem> _dpaEnum;
  549. CDPA<PaneItem> _dpaEnumNew; // Used during background enumerations
  550. int _rgiSep[MAX_SEPARATORS]; /* Only _cSep elements are meaningful */
  551. int _cSep; /* Number of separators */
  552. //
  553. // Context menu handling
  554. //
  555. IContextMenu2 * _pcm2Pop; /* Currently popped-up context menu */
  556. IContextMenu3 * _pcm3Pop; /* Currently popped-up context menu */
  557. IDropTargetHelper * _pdth; /* For cool-looking drag/drop */
  558. IDragSourceHelper * _pdsh; /* For cool-looking drag/drop */
  559. IDataObject * _pdtoDragOut; /* Data object being dragged out */
  560. IDataObject * _pdtoDragIn; /* Data object being dragged in */
  561. IDropTarget * _pdtDragOver; /* Object being dragged over (if any) */
  562. IShellTaskScheduler * _psched; /* Task scheduler */
  563. int _iDragOut; /* The item being dragged out (-1 if none) */
  564. int _iPosDragOut; /* The position of item _iDragOut */
  565. int _iDragOver; /* The item being dragged over (-1 if none) */
  566. DWORD _tmDragOver; /* Time the dragover started (to see if we need to auto-open) */
  567. int _iInsert; /* Where the insert mark should be drawn (-1 if none) */
  568. BOOL _fForceArrowCursor; /* Should we force a regular cursor during drag/drop? */
  569. BOOL _fDragToSelf; /* Are we dragging an object to ourselves? */
  570. BOOL _fInsertable; /* Is item being dragged pinnable? */
  571. DWORD _grfKeyStateLast; /* Last grfKeyState passed to DragOver */
  572. int _cyTile; /* Height of a tile */
  573. int _cxTile; /* Width of a tile */
  574. int _cyTilePadding; /* Extra vertical space between tiles */
  575. int _cySepTile; /* Height of a separator tile */
  576. int _cySep; /* Height of a separator line */
  577. int _cxMargin; /* Left margin */
  578. int _cyMargin; /* Top margin */
  579. int _cxIndent; /* So bonus texts line up with listview text */
  580. COLORREF _clrBG; /* Color for background */
  581. COLORREF _clrHot; /* Color for hot text*/
  582. COLORREF _clrSubtitle; /* Color for subtitle text*/
  583. LONG _lRef; /* Reference count */
  584. BOOL _fBGTask; /* Is a background task already scheduled? */
  585. BOOL _fRestartEnum; /* Should in-progress enumeration be restarted? */
  586. BOOL _fRestartUrgent;/* Is the _fRestartEnum urgent? */
  587. BOOL _fEnumValid; /* Is the list of items all fine? */
  588. BOOL _fNeedsRepopulate; /* Do we need to call _RepopulateList ? */
  589. BOOL _fForceChange; /* Should we act as if there was a change even if there didn't seem to be one? */
  590. ULONG _rguChangeNotify[SFTHOST_MAXNOTIFY];
  591. /* Outstanding change notification (if any) */
  592. BOOL _fAllowEditLabel; /* Is this an approved label-editing state? */
  593. HFONT _hfList; /* Custom listview font (if required) */
  594. HFONT _hfBold; /* Bold listview font (if required) */
  595. HFONT _hfMarlett; /* Marlett font (if required) */
  596. int _cxMarlett; /* Width of the menu cascade glyph */
  597. int _tmAscentMarlett; /* Font ascent for Marlett */
  598. HWND _hwndAni; /* Handle of flashlight animation, if present */
  599. UINT _idtAni; /* Animation timer handle */
  600. HBRUSH _hBrushAni; /* Background brush for the Ani window */
  601. int _cPinnedDesired;/* SetDesiredSize */
  602. int _cNormalDesired;/* SetDesiredSize */
  603. int _iCascading; /* Which item is the cascade menu appearing over? */
  604. DWORD _dwCustomDrawState; /* Keeps track of whether customdraw is real or fake */
  605. int _cPaint; /* How many (nested) paint messages are we handling? */
  606. #ifdef DEBUG
  607. BOOL _fEnumerating; /* Are we enumerating client items? */
  608. BOOL _fPopulating; /* Are we populating the listview? */
  609. BOOL _fListUnstable; /* The listview is unstable; don't get upset */
  610. //
  611. // To verify that we manage the inner drop target correctly.
  612. //
  613. enum {
  614. DRAGSTATE_UNINITIALIZED = 0,
  615. DRAGSTATE_ENTERED = 1,
  616. };
  617. int _iDragState; /* for debugging */
  618. #endif
  619. /* Large structures go at the end */
  620. };
  621. _inline SMPANEDATA* PaneDataFromCreateStruct(LPARAM lParam)
  622. {
  623. LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
  624. return reinterpret_cast<SMPANEDATA*>(lpcs->lpCreateParams);
  625. }
  626. //****************************************************************************
  627. //
  628. // Helper functions for messing with UEM info
  629. //
  630. void _GetUEMInfo(const GUID *pguidGrp, int eCmd, WPARAM wParam, LPARAM lParam, UEMINFO *pueiOut);
  631. #define _GetUEMPidlInfo(psf, pidl, pueiOut) \
  632. _GetUEMInfo(&UEMIID_SHELL, UEME_RUNPIDL, \
  633. reinterpret_cast<WPARAM>(psf), \
  634. reinterpret_cast<LPARAM>(pidl), pueiOut)
  635. #define _GetUEMPathInfo(pszPath, pueiOut) \
  636. _GetUEMInfo(&UEMIID_SHELL, UEME_RUNPATH, (WPARAM)-1, \
  637. reinterpret_cast<LPARAM>(pszPath), pueiOut)
  638. #define _SetUEMPidlInfo(psf, pidl, pueiInOut) \
  639. UEMSetEvent(&UEMIID_SHELL, UEME_RUNPIDL, \
  640. reinterpret_cast<WPARAM>(psf), \
  641. reinterpret_cast<LPARAM>(pidl), pueiInOut)
  642. #define _SetUEMPathInfo(pszPath, pueiInOut) \
  643. UEMSetEvent(&UEMIID_SHELL, UEME_RUNPATH, (WPARAM)-1, \
  644. reinterpret_cast<LPARAM>(pszPath), pueiInOut)
  645. // SOMEDAY: Figure out what UEMF_XEVENT means. I just stole the code
  646. // from startmnu.cpp.
  647. #define _FireUEMPidlEvent(psf, pidl) \
  648. UEMFireEvent(&UEMIID_SHELL, UEME_RUNPIDL, UEMF_XEVENT, \
  649. reinterpret_cast<WPARAM>(psf), \
  650. reinterpret_cast<LPARAM>(pidl))
  651. //****************************************************************************
  652. //
  653. // Constructors for derived classes
  654. //
  655. typedef SFTBarHost *(CALLBACK *PFNHOSTCONSTRUCTOR)(void);
  656. STDAPI_(SFTBarHost *) ByUsage_CreateInstance();
  657. STDAPI_(SFTBarHost *) SpecList_CreateInstance();
  658. STDAPI_(SFTBarHost *) RecentDocs_CreateInstance();
  659. #define RECTWIDTH(rc) ((rc).right-(rc).left)
  660. #define RECTHEIGHT(rc) ((rc).bottom-(rc).top)
  661. #endif // __SFTHOST_H__