Source code of Windows XP (NT5)
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.

627 lines
17 KiB

  1. // ProgView.h : Declaration of the CProgView
  2. #ifndef __PROGVIEW_H_
  3. #define __PROGVIEW_H_
  4. #include "resource.h" // main symbols
  5. #include <atlctl.h>
  6. #include <shlobj.h>
  7. #include "CompatUICP.h"
  8. /////////////////// SHIMDB
  9. extern "C" {
  10. #include "shimdb.h"
  11. }
  12. /////////////////// STL
  13. #include "AccelContainer.h"
  14. class CProgramList;
  15. class CProgView;
  16. #define IDC_REFRESH 0x1234
  17. //
  18. // Program list stuff
  19. //
  20. BOOL
  21. GetProgramListSelection(
  22. CProgramList* pProgramList
  23. );
  24. BOOL
  25. InitializeProgramList(
  26. CProgramList** ppProgramList,
  27. HWND hwndListView
  28. );
  29. BOOL
  30. CleanupProgramList(
  31. CProgramList* pProgramList
  32. );
  33. BOOL
  34. PopulateProgramList(
  35. CProgramList* pProgramList,
  36. CProgView* pProgView,
  37. HANDLE hEventCancel
  38. );
  39. BOOL
  40. GetProgramListSelectionDetails(
  41. CProgramList* pProgramList,
  42. INT iInformationClass,
  43. VARIANT* pVal
  44. );
  45. LRESULT
  46. NotifyProgramList(
  47. CProgramList* pProgramList,
  48. LPNMHDR pnmhdr,
  49. BOOL& bHandled
  50. );
  51. BOOL
  52. GetProgramListEnabled(
  53. CProgramList* pProgramList
  54. );
  55. VOID
  56. EnableProgramList(
  57. CProgramList* pProgramList,
  58. BOOL bEnable
  59. );
  60. BOOL
  61. UpdateProgramListItem(
  62. CProgramList* pProgramList,
  63. LPCWSTR pwszPath,
  64. LPCWSTR pwszKeys
  65. );
  66. #define WM_VIEW_CHANGED (WM_USER+500)
  67. #define WM_LIST_POPULATED (WM_USER+501)
  68. //
  69. // wait for the thread to cleanup
  70. //
  71. #define POPULATE_THREAD_TIMEOUT 1000
  72. /////////////////////////////////////////////////////////////////////////////
  73. // CProgView
  74. class ATL_NO_VTABLE CProgView :
  75. public CComObjectRootEx<CComSingleThreadModel>,
  76. public CStockPropImpl<CProgView, IProgView, &IID_IProgView, &LIBID_COMPATUILib>,
  77. public CComCompositeControl<CProgView>,
  78. public IPersistStreamInitImpl<CProgView>,
  79. public IOleControlImpl<CProgView>,
  80. public IOleObjectImpl<CProgView>,
  81. public IOleInPlaceActiveObjectImpl<CProgView>,
  82. public IViewObjectExImpl<CProgView>,
  83. public IOleInPlaceObjectWindowlessImpl<CProgView>,
  84. public CComCoClass<CProgView, &CLSID_ProgView>,
  85. public ISupportErrorInfo,
  86. public IPersistPropertyBagImpl<CProgView>,
  87. public IConnectionPointContainerImpl<CProgView>,
  88. public CProxy_IProgViewEvents< CProgView >,
  89. public IPropertyNotifySinkCP< CProgView >,
  90. public IProvideClassInfo2Impl<&CLSID_ProgView, &DIID__IProgViewEvents, &LIBID_COMPATUILib>,
  91. public CProxy_ISelectFileEvents< CProgView >
  92. {
  93. public:
  94. typedef enum {
  95. CMD_EXIT,
  96. CMD_CLEANUP,
  97. CMD_SCAN,
  98. CMD_NONE
  99. } PopulateCmdType;
  100. CProgView()
  101. {
  102. m_bWindowOnly = TRUE;
  103. m_pProgramList = NULL;
  104. m_bPendingPopulate = FALSE;
  105. m_bRecomposeOnResize = TRUE;
  106. m_PopulateInProgress = FALSE;
  107. m_nCmdPopulate = CMD_NONE;
  108. CalcExtent(m_sizeExtent);
  109. m_hEventCancel = CreateEvent(NULL, TRUE, FALSE, NULL);
  110. //
  111. // handle error -- we are big time in trouble if this fails
  112. //
  113. m_hEventCmd = CreateEvent(NULL, FALSE, FALSE, NULL);
  114. //
  115. // same
  116. //
  117. m_hThreadPopulate = NULL;
  118. m_pMallocUI = NULL;
  119. //
  120. // create accelerator
  121. //
  122. ACCEL rgAccel[] = { { FVIRTKEY, VK_F5, IDC_REFRESH } };
  123. m_hAccel = CreateAcceleratorTable(rgAccel, ARRAYSIZE(rgAccel));
  124. }
  125. ~CProgView() {
  126. if (m_hAccel) {
  127. DestroyAcceleratorTable(m_hAccel);
  128. }
  129. if (m_hEventCancel) {
  130. SetEvent(m_hEventCancel);
  131. CloseHandle(m_hEventCancel);
  132. }
  133. if (m_hEventCmd) {
  134. m_nCmdPopulate = CMD_EXIT;
  135. SetEvent(m_hEventCmd);
  136. CloseHandle(m_hEventCmd);
  137. }
  138. if (m_hThreadPopulate) {
  139. WaitForSingleObject(m_hThreadPopulate, POPULATE_THREAD_TIMEOUT);
  140. CloseHandle(m_hThreadPopulate);
  141. }
  142. if (m_pMallocUI) {
  143. m_pMallocUI->Release();
  144. }
  145. }
  146. DECLARE_REGISTRY_RESOURCEID(IDR_PROGVIEW)
  147. DECLARE_PROTECT_FINAL_CONSTRUCT()
  148. BEGIN_COM_MAP(CProgView)
  149. COM_INTERFACE_ENTRY(IProgView)
  150. COM_INTERFACE_ENTRY(IDispatch)
  151. COM_INTERFACE_ENTRY(IViewObjectEx)
  152. COM_INTERFACE_ENTRY(IViewObject2)
  153. COM_INTERFACE_ENTRY(IViewObject)
  154. COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless)
  155. COM_INTERFACE_ENTRY(IOleInPlaceObject)
  156. COM_INTERFACE_ENTRY2(IOleWindow, IOleInPlaceObjectWindowless)
  157. COM_INTERFACE_ENTRY(IOleInPlaceActiveObject)
  158. COM_INTERFACE_ENTRY(IOleControl)
  159. COM_INTERFACE_ENTRY(IOleObject)
  160. COM_INTERFACE_ENTRY(IPersistStreamInit)
  161. COM_INTERFACE_ENTRY2(IPersist, IPersistStreamInit)
  162. COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer)
  163. COM_INTERFACE_ENTRY(IProvideClassInfo)
  164. COM_INTERFACE_ENTRY(IProvideClassInfo2)
  165. COM_INTERFACE_ENTRY(IPersistPropertyBag)
  166. END_COM_MAP()
  167. BEGIN_PROP_MAP(CProgView)
  168. PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4)
  169. PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
  170. PROP_ENTRY("BackColor", DISPID_BACKCOLOR, CLSID_StockColorPage)
  171. // PROP_ENTRY("BorderStyle", DISPID_BORDERSTYLE, CLSID_NULL)
  172. PROP_ENTRY("Enabled", DISPID_ENABLED, CLSID_NULL)
  173. // PROP_ENTRY("ForeColor", DISPID_FORECOLOR, CLSID_StockColorPage)
  174. // PROP_ENTRY("Text", DISPID_TEXT, CLSID_NULL)
  175. // PROP_ENTRY("Tabstop", DISPID_TABSTOP, CLSID_NULL)
  176. // Example entries
  177. // PROP_ENTRY("Property Description", dispid, clsid)
  178. // PROP_PAGE(CLSID_StockColorPage)
  179. PROP_ENTRY("Accel", 7, CLSID_NULL) // the numbers should match .idl file!
  180. PROP_ENTRY("ExternAccel", 8, CLSID_NULL)
  181. PROP_ENTRY("ExcludeFiles", 9, CLSID_NULL)
  182. END_PROP_MAP()
  183. BEGIN_MSG_MAP(CProgView)
  184. NOTIFY_ID_HANDLER(IDC_LISTPROGRAMS, OnNotifyListView)
  185. NOTIFY_HANDLER(IDC_LISTPROGRAMS, NM_DBLCLK, OnDblclkListprograms)
  186. MESSAGE_HANDLER(WM_MOUSEACTIVATE, OnMouseActivate)
  187. MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
  188. MESSAGE_HANDLER(WM_VIEW_CHANGED, OnViewChanged)
  189. MESSAGE_HANDLER(WM_LIST_POPULATED, OnListPopulated)
  190. MESSAGE_HANDLER(WM_GETDLGCODE, OnGetDlgCode)
  191. MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
  192. // COMMAND_ID_HANDLER(IDC_REFRESH, OnRefreshListCmd)
  193. CHAIN_MSG_MAP(CComCompositeControl<CProgView>)
  194. END_MSG_MAP()
  195. // Handler prototypes:
  196. // LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  197. // LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
  198. // LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);
  199. BEGIN_SINK_MAP(CProgView)
  200. //Make sure the Event Handlers have __stdcall calling convention
  201. END_SINK_MAP()
  202. BEGIN_CONNECTION_POINT_MAP(CProgView)
  203. CONNECTION_POINT_ENTRY(DIID__IProgViewEvents)
  204. CONNECTION_POINT_ENTRY(DIID__ISelectFileEvents)
  205. END_CONNECTION_POINT_MAP()
  206. // ISupportsErrorInfo
  207. STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid)
  208. {
  209. static const IID* arr[] =
  210. {
  211. &IID_IProgView,
  212. };
  213. for (int i=0; i<sizeof(arr)/sizeof(arr[0]); i++)
  214. {
  215. if (InlineIsEqualGUID(*arr[i], riid))
  216. return S_OK;
  217. }
  218. return S_FALSE;
  219. }
  220. STDMETHOD(OnAmbientPropertyChange)(DISPID dispid)
  221. {
  222. if (dispid == DISPID_AMBIENT_BACKCOLOR)
  223. {
  224. SetBackgroundColorFromAmbient();
  225. FireViewChange();
  226. }
  227. return IOleControlImpl<CProgView>::OnAmbientPropertyChange(dispid);
  228. }
  229. HRESULT FireOnChanged(DISPID dispID) {
  230. if (dispID == DISPID_ENABLED) {
  231. HWND hwndList = GetDlgItem(IDC_LISTPROGRAMS);
  232. if (::IsWindow(hwndList)) {
  233. ::EnableWindow(hwndList, m_bEnabled);
  234. }
  235. }
  236. return S_OK;
  237. }
  238. STDMETHOD(GetControlInfo)(CONTROLINFO* pCI) {
  239. if (NULL == pCI) {
  240. return E_POINTER;
  241. }
  242. pCI->cb = sizeof(*pCI);
  243. pCI->hAccel = m_hAccel;
  244. pCI->cAccel = 1;
  245. pCI->dwFlags = 0;
  246. return S_OK;
  247. }
  248. STDMETHOD(OnMnemonic)(LPMSG pMsg) {
  249. if (pMsg->message == WM_COMMAND || pMsg->message == WM_SYSCOMMAND) {
  250. if (LOWORD(pMsg->wParam) == IDC_REFRESH) {
  251. PopulateList();
  252. }
  253. }
  254. return S_OK;
  255. }
  256. HRESULT InPlaceActivate(LONG iVerb, const RECT* prcPosRect = NULL);
  257. LRESULT OnNotifyListView(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);
  258. LRESULT OnDblclkListprograms(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);
  259. LRESULT OnMouseActivate(UINT, WPARAM, LPARAM, BOOL&) {
  260. // Manually activate the control
  261. InPlaceActivate(OLEIVERB_UIACTIVATE);
  262. return 0;
  263. }
  264. STDMETHOD(InPlaceDeactivate)(VOID) {
  265. HRESULT hr = IOleInPlaceObjectWindowlessImpl<CProgView>::InPlaceDeactivate();
  266. //
  267. // make sure we cancel first if we are scanning
  268. //
  269. return hr;
  270. }
  271. #if 0
  272. STDMETHOD(SetExtent)(DWORD dwDrawAspect, SIZEL* psizel) {
  273. if (IsWindow()) {
  274. HWND hlvPrograms = GetDlgItem(IDC_LISTPROGRAMS);
  275. SIZEL sizePix;
  276. AtlHiMetricToPixel(psizel, &sizePix);
  277. ::SetWindowPos(hlvPrograms, NULL, 0, 0,
  278. sizePix.cx, sizePix.cy,
  279. SWP_NOZORDER|SWP_NOACTIVATE);
  280. /*
  281. ::SetWindowPos(hlvPrograms, NULL, 0, 0,
  282. m_rcPos.right - m_rcPos.left,
  283. m_rcPos.bottom - m_rcPos.top,
  284. SWP_NOZORDER|SWP_NOACTIVATE);
  285. */
  286. }
  287. HRESULT hr = IOleObjectImpl<CProgView>::SetExtent(dwDrawAspect, psizel);
  288. return hr;
  289. }
  290. #endif
  291. LRESULT OnGetDlgCode(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  292. {
  293. // TODO : Add Code for message handler. Call DefWindowProc if necessary.
  294. if (lParam) {
  295. LPMSG pMsg = (LPMSG)lParam;
  296. if (pMsg->message == WM_SYSKEYDOWN || pMsg->message == WM_SYSCHAR) { // eat accel ?
  297. bHandled = TRUE;
  298. return DLGC_WANTMESSAGE;
  299. }
  300. }
  301. bHandled = TRUE;
  302. return DLGC_WANTTAB|DLGC_WANTARROWS|DLGC_WANTALLKEYS;
  303. }
  304. STDMETHOD(SetObjectRects)(LPCRECT prcPos, LPCRECT prcClip) {
  305. HWND hlvPrograms = GetDlgItem(IDC_LISTPROGRAMS);
  306. IOleInPlaceObjectWindowlessImpl<CProgView>::SetObjectRects(prcPos, prcClip);
  307. ::SetWindowPos(hlvPrograms, NULL, 0, 0,
  308. prcPos->right - prcPos->left,
  309. prcPos->bottom - prcPos->top,
  310. SWP_NOZORDER|SWP_NOACTIVATE);
  311. HWND hwnd;
  312. RECT rc;
  313. hwnd = GetDlgItem(IDC_STATUSLINE1);
  314. ::GetWindowRect(hwnd, &rc);
  315. //
  316. // we are happy with location, just set the width
  317. //
  318. ScreenToClient((LPPOINT)&rc);
  319. ScreenToClient(((LPPOINT)&rc) + 1);
  320. ::SetWindowPos(hwnd, NULL,
  321. rc.left, rc.top,
  322. prcPos->right - prcPos->left - rc.left,
  323. rc.bottom - rc.top,
  324. SWP_NOZORDER|SWP_NOACTIVATE);
  325. hwnd = GetDlgItem(IDC_STATUSLINE2);
  326. ::GetWindowRect(hwnd, &rc);
  327. //
  328. // we are happy with location, just set the width
  329. //
  330. ScreenToClient((LPPOINT)&rc);
  331. ScreenToClient(((LPPOINT)&rc) + 1);
  332. ::SetWindowPos(hwnd, NULL,
  333. rc.left, rc.top,
  334. prcPos->right - prcPos->left - rc.left,
  335. rc.bottom - rc.top,
  336. SWP_NOZORDER|SWP_NOACTIVATE);
  337. return S_OK;
  338. }
  339. BOOL PreTranslateAccelerator(LPMSG pMsg, HRESULT& hrRet);
  340. #if 0
  341. static CWndClassInfo& GetWndClassInfo() {
  342. DebugBreak();
  343. static CWndClassInfo wc = CWindowImpl<CProgView>::GetWndClassInfo();
  344. wc.m_wc.style &= ~(CS_HREDRAW|CS_VREDRAW);
  345. return wc;
  346. }
  347. BOOL PreTranslateAccelerator(LPMSG pMsg, HRESULT& hrRet) {
  348. HWND hwndList = GetDlgItem(IDC_LISTPROGRAMS);
  349. HWND hwndFocus = GetFocus();
  350. if (hwndList != hwndFocus || !::IsWindowEnabled(hwndList)) {
  351. goto PropagateAccel;
  352. }
  353. if (pMsg->message == WM_KEYDOWN) {
  354. if (pMsg->wParam == VK_LEFT ||
  355. pMsg->wParam == VK_RIGHT ||
  356. pMsg->wParam == VK_UP ||
  357. pMsg->wParam == VK_DOWN) {
  358. SendDlgItemMessage(IDC_LISTPROGRAMS, pMsg->message, pMsg->wParam, pMsg->lParam);
  359. hrRet = S_OK;
  360. return TRUE;
  361. }
  362. if (LOWORD(pMsg->wParam) == VK_RETURN || LOWORD(pMsg->wParam) == VK_EXECUTE) {
  363. if (ListView_GetNextItem(hwndList, -1, LVNI_SELECTED) >= 0) {
  364. Fire_DblClk(0);
  365. hrRet = S_OK;
  366. return TRUE;
  367. }
  368. }
  369. if (LOWORD(pMsg->wParam) == VK_TAB) {
  370. goto PropagateAccel;
  371. }
  372. }
  373. if (IsDialogMessage(pMsg)) {
  374. hrRet = S_OK;
  375. return TRUE;
  376. }
  377. if (::TranslateAccelerator(m_hWnd, NULL, pMsg)) {
  378. hrRet = S_OK;
  379. return TRUE;
  380. }
  381. PropagateAccel:
  382. return FALSE;
  383. }
  384. #endif
  385. // IViewObjectEx
  386. DECLARE_VIEW_STATUS(0)
  387. // IProgView
  388. public:
  389. STDMETHOD(get_ExcludeFiles)(/*[out, retval]*/ BSTR* pVal);
  390. STDMETHOD(put_ExcludeFiles)(/*[in]*/ BSTR newVal);
  391. STDMETHOD(get_ExternAccel)(/*[out, retval]*/ BSTR *pVal);
  392. STDMETHOD(put_ExternAccel)(/*[in]*/ BSTR newVal);
  393. #if 0
  394. STDMETHOD(get_Accel)(/*[out, retval]*/ BSTR *pVal);
  395. STDMETHOD(put_Accel)(/*[in]*/ BSTR newVal);
  396. #endif
  397. STDMETHOD(CancelPopulateList)();
  398. STDMETHOD(UpdateListItem)(/*[in]*/BSTR pTarget, /*[in]*/VARIANT* pKeys, /*[out, retval]*/ BOOL* pResult);
  399. STDMETHOD(PopulateList)();
  400. STDMETHOD(GetSelectionInformation)(LONG, VARIANT* pVal);
  401. STDMETHOD(get_SelectionName)(/*[out, retval]*/ VARIANT *pVal);
  402. STDMETHOD(GetSelectedItem)();
  403. STDMETHOD(ClearAccel)();
  404. STDMETHOD(ClearExternAccel)();
  405. STDMETHOD(get_AccelCmd)(/*[in]*/ LONG lCmd, /*[out, retval]*/ BSTR *pVal);
  406. STDMETHOD(put_AccelCmd)(/*[in]*/ LONG lCmd, /*[in]*/ BSTR newVal);
  407. BOOL m_bEnabled;
  408. BOOL m_bPendingPopulate;
  409. CProgramList* m_pProgramList;
  410. enum { IDD = IDD_PROGVIEW };
  411. LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
  412. // TODO : Add Code for message handler. Call DefWindowProc if necessary.
  413. /*
  414. DWORD dwStyle = (DWORD)GetClassLong(m_hWnd, GCL_STYLE);
  415. dwStyle &= ~(CS_HREDRAW | CS_VREDRAW);
  416. SetClassLong(m_hWnd, GCL_STYLE, dwStyle);
  417. */
  418. //
  419. // before we start messing around with this... obtain malloc for the UI thread
  420. //
  421. HRESULT hr = SHGetMalloc(&m_pMallocUI);
  422. if (!SUCCEEDED(hr)) {
  423. //
  424. // aww -- ui malloc will not be available -- we're pretty much hosed
  425. //
  426. m_pMallocUI = NULL;
  427. }
  428. PopulateList();
  429. return 0;
  430. }
  431. static DWORD WINAPI _PopulateThreadProc(LPVOID lpvParam);
  432. VOID UpdatePopulateStatus(LPCTSTR lpszName, LPCTSTR lpszPath) {
  433. SetDlgItemText(IDC_STATUSLINE1, lpszName);
  434. ::PathSetDlgItemPath(m_hWnd, IDC_STATUSLINE2, lpszPath);
  435. }
  436. VOID ShowProgressWindows(BOOL bProgress = FALSE);
  437. LRESULT OnViewChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
  438. FireViewChange();
  439. bHandled = TRUE;
  440. return 0;
  441. }
  442. LRESULT OnListPopulated(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
  443. Fire_ProgramListReady();
  444. bHandled = TRUE;
  445. return 0;
  446. }
  447. BOOL PopulateListInternal();
  448. HANDLE m_hEventCancel;
  449. LONG m_PopulateInProgress;
  450. HANDLE m_hEventCmd;
  451. PopulateCmdType m_nCmdPopulate;
  452. HANDLE m_hThreadPopulate;
  453. IMalloc* m_pMallocUI;
  454. HACCEL m_hAccel;
  455. BOOL IsScanInProgress(VOID) {
  456. return InterlockedCompareExchange(&m_PopulateInProgress, TRUE, TRUE) == TRUE;
  457. }
  458. /*
  459. LRESULT OnRefreshListCmd(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) {
  460. PopulateList();
  461. bHandled = TRUE;
  462. return 0;
  463. }
  464. */
  465. //
  466. // accelerators
  467. //
  468. CAccelContainer m_Accel; // my own accelerator
  469. CAccelContainer m_ExternAccel; // external accels
  470. LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  471. {
  472. InPlaceActivate(OLEIVERB_UIACTIVATE);
  473. //
  474. // if we are scanning then we don't need to do anything, else - set the focus to listview
  475. //
  476. if (!IsScanInProgress()) {
  477. ::SetFocus(GetDlgItem(IDC_LISTPROGRAMS));
  478. }
  479. return CComCompositeControl<CProgView>::OnSetFocus(uMsg, wParam, lParam, bHandled);
  480. }
  481. //
  482. // blacklisted files
  483. //
  484. typedef set<wstring> STRSET;
  485. STRSET m_ExcludedFiles;
  486. //
  487. // check whether a file is excluded
  488. //
  489. BOOL IsFileExcluded(LPCTSTR pszFile);
  490. };
  491. #endif //__PROGVIEW_H_