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.

485 lines
15 KiB

  1. // SelectFile.h : Declaration of the CSelectFile
  2. #ifndef __SELECTFILE_H_
  3. #define __SELECTFILE_H_
  4. #include "resource.h" // main symbols
  5. #include <atlctl.h>
  6. #include "compatuiCP.h"
  7. extern "C" {
  8. #include "shimdb.h"
  9. }
  10. #pragma warning(disable:4786)
  11. #include <string>
  12. #include <xstring>
  13. #include <map>
  14. #include <locale>
  15. #include <algorithm>
  16. #include <vector>
  17. using namespace std;
  18. //
  19. // Accel containment code
  20. //
  21. #include "AccelContainer.h"
  22. //
  23. // in ProgList.cpp
  24. //
  25. BOOL
  26. ValidateExecutableFile(
  27. LPCTSTR pszPath,
  28. BOOL bValidateFileExists
  29. );
  30. //
  31. // in util.cpp
  32. //
  33. wstring
  34. ShimUnquotePath(
  35. LPCTSTR pwszFileName
  36. );
  37. BOOL
  38. ShimExpandEnvironmentVars(
  39. LPCTSTR lpszCmd,
  40. CComBSTR& bstr
  41. );
  42. /////////////////////////////////////////////////////////////////////////////
  43. // CSelectFile
  44. class ATL_NO_VTABLE CSelectFile :
  45. public CComObjectRootEx<CComSingleThreadModel>,
  46. public CStockPropImpl<CSelectFile, ISelectFile, &IID_ISelectFile, &LIBID_COMPATUILib>,
  47. public CComCompositeControl<CSelectFile>,
  48. public IPersistStreamInitImpl<CSelectFile>,
  49. public IOleControlImpl<CSelectFile>,
  50. public IOleObjectImpl<CSelectFile>,
  51. public IOleInPlaceActiveObjectImpl<CSelectFile>,
  52. public IViewObjectExImpl<CSelectFile>,
  53. public IOleInPlaceObjectWindowlessImpl<CSelectFile>,
  54. public CComCoClass<CSelectFile, &CLSID_SelectFile>,
  55. public ISupportErrorInfo,
  56. public IPersistPropertyBagImpl<CSelectFile>,
  57. public IConnectionPointContainerImpl<CSelectFile>,
  58. public CProxy_ISelectFileEvents< CSelectFile >,
  59. public IPropertyNotifySinkCP< CSelectFile >,
  60. public IProvideClassInfo2Impl<&CLSID_SelectFile, &DIID__ISelectFileEvents, &LIBID_COMPATUILib>,
  61. public CProxy_IProgViewEvents< CSelectFile >
  62. {
  63. public:
  64. CSelectFile() :
  65. m_dwBrowseFlags(0), m_Safe(this)
  66. {
  67. m_bWindowOnly = TRUE;
  68. m_bTabStop = TRUE;
  69. m_bMouseActivate = FALSE;
  70. CalcExtent(m_sizeExtent);
  71. }
  72. DECLARE_REGISTRY_RESOURCEID(IDR_SELECTFILE)
  73. DECLARE_PROTECT_FINAL_CONSTRUCT()
  74. BEGIN_COM_MAP(CSelectFile)
  75. COM_INTERFACE_ENTRY(ISelectFile)
  76. COM_INTERFACE_ENTRY(IDispatch)
  77. COM_INTERFACE_ENTRY(IViewObjectEx)
  78. COM_INTERFACE_ENTRY(IViewObject2)
  79. COM_INTERFACE_ENTRY(IViewObject)
  80. COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless)
  81. COM_INTERFACE_ENTRY(IOleInPlaceObject)
  82. COM_INTERFACE_ENTRY2(IOleWindow, IOleInPlaceObjectWindowless)
  83. COM_INTERFACE_ENTRY(IOleInPlaceActiveObject)
  84. COM_INTERFACE_ENTRY(IOleControl)
  85. COM_INTERFACE_ENTRY(IOleObject)
  86. COM_INTERFACE_ENTRY(IPersistStreamInit)
  87. COM_INTERFACE_ENTRY2(IPersist, IPersistStreamInit)
  88. // COM_INTERFACE_ENTRY(ISupportErrorInfo)
  89. // COM_INTERFACE_ENTRY(IConnectionPointContainer)
  90. COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer)
  91. COM_INTERFACE_ENTRY(IProvideClassInfo2)
  92. COM_INTERFACE_ENTRY(IProvideClassInfo)
  93. COM_INTERFACE_ENTRY(IPersistPropertyBag)
  94. END_COM_MAP()
  95. BEGIN_PROP_MAP(CSelectFile)
  96. PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4)
  97. PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
  98. PROP_ENTRY("BackColor", DISPID_BACKCOLOR, CLSID_StockColorPage)
  99. PROP_ENTRY("BackStyle", DISPID_BACKSTYLE, CLSID_NULL)
  100. // PROP_ENTRY("BorderColor", DISPID_BORDERCOLOR, CLSID_StockColorPage)
  101. // PROP_ENTRY("BorderVisible", DISPID_BORDERVISIBLE, CLSID_NULL)
  102. PROP_ENTRY("Enabled", DISPID_ENABLED, CLSID_NULL)
  103. // Example entries
  104. // PROP_ENTRY("Property Description", dispid, clsid)
  105. // PROP_PAGE(CLSID_StockColorPage)
  106. PROP_ENTRY("Accel", 7, CLSID_NULL)
  107. PROP_ENTRY("ExternAccel", 8, CLSID_NULL)
  108. PROP_ENTRY("BrowseBtnCaption", 9, CLSID_NULL)
  109. END_PROP_MAP()
  110. BEGIN_CONNECTION_POINT_MAP(CSelectFile)
  111. CONNECTION_POINT_ENTRY(DIID__ISelectFileEvents)
  112. // CONNECTION_POINT_ENTRY(IID_IPropertyNotifySink)
  113. CONNECTION_POINT_ENTRY(DIID__IProgViewEvents)
  114. END_CONNECTION_POINT_MAP()
  115. BEGIN_MSG_MAP(CSelectFile)
  116. COMMAND_HANDLER(IDC_BROWSE, BN_CLICKED, OnClickedBrowse)
  117. // MESSAGE_HANDLER(WM_CTLCOLORDLG, OnColorDlg)
  118. // MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnColorDlg)
  119. MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
  120. MESSAGE_HANDLER(WM_MOUSEACTIVATE, OnMouseActivate)
  121. MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
  122. CHAIN_MSG_MAP(CComCompositeControl<CSelectFile>)
  123. // ALT_MSG_MAP(1)
  124. END_MSG_MAP()
  125. // Handler prototypes:
  126. // LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  127. // LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
  128. // LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);
  129. BEGIN_SINK_MAP(CSelectFile)
  130. //Make sure the Event Handlers have __stdcall calling convention
  131. END_SINK_MAP()
  132. STDMETHOD(OnAmbientPropertyChange)(DISPID dispid)
  133. {
  134. if (dispid == DISPID_AMBIENT_BACKCOLOR)
  135. {
  136. SetBackgroundColorFromAmbient();
  137. FireViewChange();
  138. }
  139. return IOleControlImpl<CSelectFile>::OnAmbientPropertyChange(dispid);
  140. }
  141. HRESULT FireOnChanged(DISPID dispID) {
  142. if (dispID == DISPID_ENABLED) {
  143. ::EnableWindow(GetDlgItem(IDC_EDITFILENAME), m_bEnabled);
  144. ::EnableWindow(GetDlgItem(IDC_BROWSE), m_bEnabled);
  145. }
  146. return S_OK;
  147. }
  148. STDMETHOD(GetControlInfo)(CONTROLINFO* pCI) {
  149. if (NULL == pCI) {
  150. return E_POINTER;
  151. }
  152. pCI->hAccel = NULL;
  153. pCI->cAccel = 0;
  154. pCI->dwFlags = 0;
  155. return S_OK;
  156. }
  157. // ISupportsErrorInfo
  158. STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid)
  159. {
  160. static const IID* arr[] =
  161. {
  162. &IID_ISelectFile,
  163. };
  164. for (int i=0; i<sizeof(arr)/sizeof(arr[0]); i++)
  165. {
  166. if (InlineIsEqualGUID(*arr[i], riid))
  167. return S_OK;
  168. }
  169. return S_FALSE;
  170. }
  171. STDMETHOD(SetExtent)(DWORD dwDrawAspect, SIZEL* psizel) {
  172. HRESULT hr = IOleObjectImpl<CSelectFile>::SetExtent(dwDrawAspect, psizel);
  173. PositionControls();
  174. return hr;
  175. }
  176. STDMETHOD(SetObjectRects)(LPCRECT prcPos, LPCRECT prcClip) {
  177. IOleInPlaceObjectWindowlessImpl<CSelectFile>::SetObjectRects(prcPos, prcClip);
  178. PositionControls(prcPos);
  179. return S_OK;
  180. }
  181. HRESULT InPlaceActivate(LONG iVerb, const RECT* prcPosRect = NULL) {
  182. HRESULT hr = CComCompositeControl<CSelectFile>::InPlaceActivate(iVerb, prcPosRect);
  183. Fire_StateChanged(iVerb);
  184. return hr;
  185. }
  186. STDMETHOD(UIDeactivate)() {
  187. HRESULT hr = IOleInPlaceObjectWindowlessImpl<CSelectFile>::UIDeactivate();
  188. //
  189. // We are being deactivated
  190. // when we loose focus, nuke default button out of here
  191. //
  192. DWORD dwDefBtn = (DWORD)SendMessage(DM_GETDEFID, 0);
  193. if (HIWORD(dwDefBtn) == DC_HASDEFID) {
  194. // SendMessage(DM_SETDEFID, IDC_EDITFILENAME); // basically forget the default button
  195. dwDefBtn = LOWORD(dwDefBtn);
  196. DWORD dwStyle = ::GetWindowLong(GetDlgItem(dwDefBtn), GWL_STYLE);
  197. if (dwStyle & BS_DEFPUSHBUTTON) {
  198. dwStyle &= ~BS_DEFPUSHBUTTON;
  199. dwStyle |= BS_PUSHBUTTON;
  200. SendDlgItemMessage(dwDefBtn, BM_SETSTYLE, dwStyle, TRUE);
  201. }
  202. }
  203. // send killfocus
  204. SendMessage(WM_KILLFOCUS);
  205. return hr;
  206. }
  207. LRESULT OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  208. {
  209. // Manually activate the control
  210. LRESULT lRes = CComCompositeControl<CSelectFile>::OnMouseActivate(uMsg, wParam, lParam, bHandled);
  211. m_bMouseActivate = TRUE;
  212. return 0;
  213. }
  214. BOOL PreTranslateAccelerator(LPMSG pMsg, HRESULT& hrRet);
  215. // IViewObjectEx
  216. DECLARE_VIEW_STATUS(0)
  217. // ISelectFile
  218. public:
  219. STDMETHOD(ClearAccel)();
  220. STDMETHOD(ClearExternAccel)();
  221. STDMETHOD(get_AccelCmd)(/*[in]*/ LONG lCmd, /*[out, retval]*/ BSTR *pVal);
  222. STDMETHOD(put_AccelCmd)(/*[in]*/ LONG lCmd, /*[in]*/ BSTR newVal);
  223. STDMETHOD(get_BrowseBtnCaption)(/*[out, retval]*/ BSTR *pVal);
  224. STDMETHOD(put_BrowseBtnCaption)(/*[in]*/ BSTR newVal);
  225. STDMETHOD(get_ExternAccel)(/*[out, retval]*/ BSTR *pVal);
  226. STDMETHOD(put_ExternAccel)(/*[in]*/ BSTR newVal);
  227. #if 0
  228. STDMETHOD(get_Accel)(/*[out, retval]*/ BSTR *pVal);
  229. STDMETHOD(put_Accel)(/*[in]*/ BSTR newVal);
  230. #endif
  231. STDMETHOD(get_ErrorCode)(/*[out, retval]*/ long *pVal);
  232. STDMETHOD(get_FileName)(/*[out, retval]*/ BSTR *pVal);
  233. STDMETHOD(put_FileName)(/*[in]*/ BSTR newVal);
  234. STDMETHOD(get_BrowseFlags)(/*[out, retval]*/ long *pVal);
  235. STDMETHOD(put_BrowseFlags)(/*[in]*/ long newVal);
  236. STDMETHOD(get_BrowseInitialDirectory)(/*[out, retval]*/ BSTR *pVal);
  237. STDMETHOD(put_BrowseInitialDirectory)(/*[in]*/ BSTR newVal);
  238. STDMETHOD(get_BrowseFilter)(/*[out, retval]*/ BSTR *pVal);
  239. STDMETHOD(put_BrowseFilter)(/*[in]*/ BSTR newVal);
  240. STDMETHOD(get_BrowseTitle)(/*[out, retval]*/ BSTR *pVal);
  241. STDMETHOD(put_BrowseTitle)(/*[in]*/ BSTR newVal);
  242. OLE_COLOR m_clrBackColor;
  243. LONG m_nBackStyle;
  244. OLE_COLOR m_clrBorderColor;
  245. BOOL m_bBorderVisible;
  246. BOOL m_bEnabled;
  247. // browse dialog props
  248. CComBSTR m_bstrTitle;
  249. CComBSTR m_bstrFilter;
  250. CComBSTR m_bstrInitialDirectory;
  251. CComBSTR m_bstrFileName;
  252. DWORD m_dwBrowseFlags;
  253. DWORD m_dwErrorCode;
  254. wstring m_BrowseBtnCaption;
  255. BOOL m_bMouseActivate;
  256. enum { IDD = IDD_SELECTFILE };
  257. LRESULT OnClickedBrowse(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
  258. protected:
  259. CSafeObject m_Safe;
  260. VOID PositionControls(LPCRECT lprc = NULL) {
  261. if (NULL == lprc) {
  262. lprc = &m_rcPos;
  263. }
  264. if (IsWindow()) {
  265. // position the edit ctl first
  266. HDWP hdwp = BeginDeferWindowPos(2);
  267. HWND hedit = GetDlgItem(IDC_EDITFILENAME);
  268. HWND hbtn = GetDlgItem(IDC_BROWSE);
  269. LONG lWidthEdit;
  270. LONG lWidthBtn;
  271. RECT rcBtn;
  272. RECT rcEdit;
  273. LONG lSpace = ::GetSystemMetrics(SM_CXFRAME);
  274. ::GetWindowRect(hbtn, &rcBtn); // get the rectangle for the button
  275. ::GetWindowRect(hedit, &rcEdit);
  276. lWidthBtn = rcBtn.right - rcBtn.left; // width of the button - 1
  277. lWidthEdit = lprc->right - lprc->left - lSpace - lWidthBtn;
  278. hdwp = ::DeferWindowPos(hdwp, hedit, NULL, 0, 0, lWidthEdit, rcEdit.bottom - rcEdit.top, SWP_NOZORDER);
  279. hdwp = ::DeferWindowPos(hdwp, hbtn, NULL, lWidthEdit + lSpace, 0, lWidthBtn, rcBtn.bottom - rcBtn.top, SWP_NOZORDER);
  280. ::EndDeferWindowPos(hdwp);
  281. }
  282. }
  283. LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
  284. WORD wCmd = 0;
  285. //
  286. // determine whether we came here with accel
  287. //
  288. CComCompositeControl<CSelectFile>::OnSetFocus(uMsg, wParam, lParam, bHandled);
  289. if (!m_bMouseActivate) {
  290. DoVerbUIActivate(&m_rcPos, NULL);
  291. if (m_Accel.IsAccelKey(NULL, &wCmd)) {
  292. //
  293. // we are to be accelerated
  294. // we look into the accel cmd to see what is there
  295. //
  296. switch(wCmd) {
  297. case IDC_BROWSE:
  298. ::SetFocus(GetDlgItem(IDC_BROWSE));
  299. OnClickedBrowse(BN_CLICKED, IDC_BROWSE, GetDlgItem(IDC_BROWSE), bHandled);
  300. break;
  301. case IDC_EDITFILENAME:
  302. ::SetFocus(GetDlgItem(IDC_EDITFILENAME));
  303. break;
  304. }
  305. }
  306. //
  307. // did we arrive here with the tab?
  308. //
  309. if (!IsChild(GetFocus())) {
  310. if (GetKeyState(VK_TAB) & 0x8000) { // was that the tab key ?
  311. HWND hwndFirst = GetNextDlgTabItem(NULL, FALSE); // first
  312. HWND hwndLast = GetNextDlgTabItem(hwndFirst, TRUE);
  313. if ((GetKeyState(VK_SHIFT) & 0x8000)) {
  314. // aha, came here with a shift-tab! -- what is the last control ?
  315. ::SetFocus(hwndLast);
  316. } else {
  317. ::SetFocus(hwndFirst);
  318. }
  319. } else {
  320. ::SetFocus(GetDlgItem(IDC_EDITFILENAME));
  321. }
  322. }
  323. }
  324. //
  325. // set the default pushbutton
  326. //
  327. SendMessage(DM_SETDEFID, IDC_BROWSE);
  328. SendDlgItemMessage(IDC_BROWSE, BM_SETSTYLE, BS_DEFPUSHBUTTON);
  329. m_bMouseActivate = FALSE;
  330. bHandled = TRUE;
  331. return 0;
  332. }
  333. LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  334. {
  335. /* // this code sets the same font as the container is using
  336. // we do not care for now, we're using MS Shell Dlg instead
  337. CComVariant varFont;
  338. HFONT hFont;
  339. HWND hwnd;
  340. HRESULT hr = GetAmbientProperty(DISPID_AMBIENT_FONT, varFont);
  341. if (SUCCEEDED(hr)) {
  342. CComQIPtr<IFont, &IID_IFont> pFont (varFont.pdispVal);
  343. if (SUCCEEDED(pFont->get_hFont(&hFont))) {
  344. for (hwnd = GetTopWindow(); hwnd != NULL;
  345. hwnd = ::GetNextWindow(hwnd, GW_HWNDNEXT)) {
  346. ::SendMessage(hwnd, WM_SETFONT, (WPARAM)hFont, TRUE);
  347. }
  348. }
  349. }
  350. */
  351. SHAutoComplete(GetDlgItem(IDC_EDITFILENAME), SHACF_FILESYSTEM);
  352. if (m_BrowseBtnCaption.length()) {
  353. SetDlgItemText(IDC_BROWSE, m_BrowseBtnCaption.c_str());
  354. }
  355. //
  356. // show ui hints
  357. //
  358. SendMessage(WM_CHANGEUISTATE, MAKEWPARAM(UIS_CLEAR, UISF_HIDEACCEL | UISF_HIDEFOCUS));
  359. return 0;
  360. }
  361. //
  362. // Accelerators
  363. //
  364. CAccelContainer m_Accel;
  365. CAccelContainer m_ExternAccel;
  366. BOOL GetFileNameFromUI(wstring& sFileName) {
  367. BSTR bstrFileName = NULL;
  368. BOOL bReturn = FALSE;
  369. bReturn = GetDlgItemText(IDC_EDITFILENAME, bstrFileName);
  370. if (bReturn) {
  371. sFileName = ShimUnquotePath(bstrFileName);
  372. //
  373. // now also expand environment variables
  374. //
  375. if (!sFileName.empty()) {
  376. CComBSTR bstrExpanded;
  377. ShimExpandEnvironmentVars(sFileName.c_str(), bstrExpanded);
  378. sFileName = bstrExpanded;
  379. }
  380. } else {
  381. sFileName.erase();
  382. }
  383. if (bstrFileName) {
  384. ::SysFreeString(bstrFileName);
  385. }
  386. return bReturn;
  387. }
  388. };
  389. #endif //__SELECTFILE_H_