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.

416 lines
13 KiB

  1. #include "stdafx.h"
  2. #include "hostutil.h"
  3. #define DEFAULT_BALLOON_TIMEOUT (10*1000) // 10 seconds
  4. LRESULT CALLBACK BalloonTipSubclassProc(
  5. HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
  6. UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
  7. {
  8. switch (uMsg)
  9. {
  10. case WM_TIMER:
  11. // Our autodismiss timer
  12. if (uIdSubclass == wParam)
  13. {
  14. KillTimer(hwnd, wParam);
  15. DestroyWindow(hwnd);
  16. return 0;
  17. }
  18. break;
  19. // On a settings change, recompute our size and margins
  20. case WM_SETTINGCHANGE:
  21. MakeMultilineTT(hwnd);
  22. break;
  23. case WM_NCDESTROY:
  24. RemoveWindowSubclass(hwnd, BalloonTipSubclassProc, uIdSubclass);
  25. break;
  26. }
  27. return DefSubclassProc(hwnd, uMsg, wParam, lParam);
  28. }
  29. //
  30. // A "fire and forget" balloon tip. Tell it where to go, what font
  31. // to use, and what to say, and it pops up and times out.
  32. //
  33. HWND CreateBalloonTip(HWND hwndOwner, int x, int y, HFONT hf,
  34. UINT idsTitle, UINT idsText)
  35. {
  36. DWORD dwStyle = TTS_ALWAYSTIP | TTS_BALLOON | TTS_NOPREFIX;
  37. HWND hwnd = CreateWindowEx(0, TOOLTIPS_CLASS, NULL, dwStyle,
  38. 0, 0, 0, 0,
  39. hwndOwner, NULL,
  40. _Module.GetModuleInstance(), NULL);
  41. if (hwnd)
  42. {
  43. MakeMultilineTT(hwnd);
  44. TCHAR szBuf[MAX_PATH];
  45. TOOLINFO ti;
  46. ti.cbSize = sizeof(ti);
  47. ti.hwnd = hwndOwner;
  48. ti.uId = reinterpret_cast<UINT_PTR>(hwndOwner);
  49. ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS | TTF_TRACK;
  50. ti.hinst = _Module.GetResourceInstance();
  51. // We can't use MAKEINTRESOURCE because that allows only up to 80
  52. // characters for text, and our text can be longer than that.
  53. ti.lpszText = szBuf;
  54. if (LoadString(_Module.GetResourceInstance(), idsText, szBuf, ARRAYSIZE(szBuf)))
  55. {
  56. SendMessage(hwnd, TTM_ADDTOOL, 0, reinterpret_cast<LPARAM>(&ti));
  57. if (idsTitle &&
  58. LoadString(_Module.GetResourceInstance(), idsTitle, szBuf, ARRAYSIZE(szBuf)))
  59. {
  60. SendMessage(hwnd, TTM_SETTITLE, TTI_INFO, reinterpret_cast<LPARAM>(szBuf));
  61. }
  62. SendMessage(hwnd, TTM_TRACKPOSITION, 0, MAKELONG(x, y));
  63. if (hf)
  64. {
  65. SetWindowFont(hwnd, hf, FALSE);
  66. }
  67. SendMessage(hwnd, TTM_TRACKACTIVATE, TRUE, reinterpret_cast<LPARAM>(&ti));
  68. // Set the autodismiss timer
  69. if (SetWindowSubclass(hwnd, BalloonTipSubclassProc, (UINT_PTR)hwndOwner, 0))
  70. {
  71. SetTimer(hwnd, (UINT_PTR)hwndOwner, DEFAULT_BALLOON_TIMEOUT, NULL);
  72. }
  73. }
  74. }
  75. return hwnd;
  76. }
  77. // Make the tooltip control multiline (infotip or balloon tip).
  78. // The size computations are the same ones that comctl32 uses
  79. // for listview and treeview infotips.
  80. void MakeMultilineTT(HWND hwndTT)
  81. {
  82. HWND hwndOwner = GetWindow(hwndTT, GW_OWNER);
  83. HDC hdc = GetDC(hwndOwner);
  84. if (hdc)
  85. {
  86. int iWidth = MulDiv(GetDeviceCaps(hdc, LOGPIXELSX), 300, 72);
  87. int iMaxWidth = GetDeviceCaps(hdc, HORZRES) * 3 / 4;
  88. SendMessage(hwndTT, TTM_SETMAXTIPWIDTH, 0, min(iWidth, iMaxWidth));
  89. static const RECT rcMargin = {4, 4, 4, 4};
  90. SendMessage(hwndTT, TTM_SETMARGIN, 0, (LPARAM)&rcMargin);
  91. ReleaseDC(hwndOwner, hdc);
  92. }
  93. }
  94. CPropBagFromReg::CPropBagFromReg(HKEY hk)
  95. {
  96. _cref = 1;
  97. _hk = hk;
  98. };
  99. CPropBagFromReg::~CPropBagFromReg()
  100. {
  101. RegCloseKey(_hk);
  102. }
  103. STDMETHODIMP CPropBagFromReg::QueryInterface(REFIID riid, PVOID *ppvObject)
  104. {
  105. if (IsEqualIID(riid, IID_IPropertyBag))
  106. *ppvObject = (IPropertyBag *)this;
  107. else if (IsEqualIID(riid, IID_IUnknown))
  108. *ppvObject = this;
  109. else
  110. {
  111. *ppvObject = NULL;
  112. return E_NOINTERFACE;
  113. }
  114. AddRef();
  115. return S_OK;
  116. }
  117. ULONG CPropBagFromReg::AddRef(void)
  118. {
  119. return ++_cref; // on the stack
  120. }
  121. ULONG CPropBagFromReg::Release(void)
  122. {
  123. if (--_cref)
  124. return _cref;
  125. delete this;
  126. return 0;
  127. }
  128. STDMETHODIMP CPropBagFromReg::Read(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog)
  129. {
  130. VARTYPE vtDesired = pVar->vt;
  131. WCHAR szTmp[100];
  132. DWORD cb = sizeof(szTmp);
  133. DWORD dwType;
  134. if (ERROR_SUCCESS == RegQueryValueExW(_hk, pszPropName, NULL, &dwType, (LPBYTE)szTmp, &cb) && (REG_SZ==dwType))
  135. {
  136. // TODO - use dwType to set the vt properly
  137. pVar->bstrVal = SysAllocString(szTmp);
  138. if (pVar->bstrVal)
  139. {
  140. pVar->vt = VT_BSTR;
  141. return VariantChangeTypeForRead(pVar, vtDesired);
  142. }
  143. else
  144. return E_OUTOFMEMORY;
  145. }
  146. else
  147. return E_INVALIDARG;
  148. }
  149. HRESULT CreatePropBagFromReg(LPCTSTR pszKey, IPropertyBag**pppb)
  150. {
  151. HRESULT hr = E_OUTOFMEMORY;
  152. *pppb = NULL;
  153. // Try current user 1st, if that fails, fall back to localmachine
  154. HKEY hk;
  155. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, pszKey, NULL, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &hk)
  156. || ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, pszKey, NULL, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &hk))
  157. {
  158. CPropBagFromReg* pcpbfi = new CPropBagFromReg(hk);
  159. if (pcpbfi)
  160. {
  161. hr = pcpbfi->QueryInterface(IID_IPropertyBag, (void**) pppb);
  162. pcpbfi->Release();
  163. }
  164. else
  165. {
  166. RegCloseKey(hk);
  167. }
  168. }
  169. return hr;
  170. };
  171. BOOL RectFromStrW(LPCWSTR pwsz, RECT *pr)
  172. {
  173. pr->left = StrToIntW(pwsz);
  174. pwsz = StrChrW(pwsz, L',');
  175. if (!pwsz)
  176. return FALSE;
  177. pr->top = StrToIntW(++pwsz);
  178. pwsz = StrChrW(pwsz, L',');
  179. if (!pwsz)
  180. return FALSE;
  181. pr->right = StrToIntW(++pwsz);
  182. pwsz = StrChrW(pwsz, L',');
  183. if (!pwsz)
  184. return FALSE;
  185. pr->bottom = StrToIntW(++pwsz);
  186. return TRUE;
  187. }
  188. LRESULT HandleApplyRegion(HWND hwnd, HTHEME hTheme,
  189. PSMNMAPPLYREGION par, int iPartId, int iStateId)
  190. {
  191. if (hTheme)
  192. {
  193. RECT rc;
  194. GetWindowRect(hwnd, &rc);
  195. // Map to caller's coordinates
  196. MapWindowRect(NULL, par->hdr.hwndFrom, &rc);
  197. HRGN hrgn;
  198. if (SUCCEEDED(GetThemeBackgroundRegion(hTheme, NULL, iPartId, iStateId, &rc, &hrgn)) && hrgn)
  199. {
  200. // Replace our window rectangle with the region
  201. HRGN hrgnRect = CreateRectRgnIndirect(&rc);
  202. if (hrgnRect)
  203. {
  204. // We want to take par->hrgn, subtract hrgnRect and add hrgn.
  205. // But we want to do this with a single operation to par->hrgn
  206. // so we don't end up with a corrupted region on low memory failure.
  207. // So we do
  208. //
  209. // par->hrgn ^= hrgnRect ^ hrgn.
  210. //
  211. // If hrgnRect ^ hrgn == NULLREGION then the background
  212. // does not want to customize the rectangle so we can just
  213. // leave par->hrgn alone.
  214. int iResult = CombineRgn(hrgn, hrgn, hrgnRect, RGN_XOR);
  215. if (iResult != ERROR && iResult != NULLREGION)
  216. {
  217. CombineRgn(par->hrgn, par->hrgn, hrgn, RGN_XOR);
  218. }
  219. DeleteObject(hrgnRect);
  220. }
  221. DeleteObject(hrgn);
  222. }
  223. }
  224. return 0;
  225. }
  226. //****************************************************************************
  227. //
  228. // CAccessible - Most of this class is just forwarders
  229. #define ACCESSIBILITY_FORWARD(fn, typedargs, args) \
  230. HRESULT CAccessible::fn typedargs \
  231. { \
  232. return _paccInner->fn args; \
  233. }
  234. ACCESSIBILITY_FORWARD(get_accParent,
  235. (IDispatch **ppdispParent),
  236. (ppdispParent))
  237. ACCESSIBILITY_FORWARD(GetTypeInfoCount,
  238. (UINT *pctinfo),
  239. (pctinfo))
  240. ACCESSIBILITY_FORWARD(GetTypeInfo,
  241. (UINT itinfo, LCID lcid, ITypeInfo **pptinfo),
  242. (itinfo, lcid, pptinfo))
  243. ACCESSIBILITY_FORWARD(GetIDsOfNames,
  244. (REFIID riid, OLECHAR **rgszNames, UINT cNames,
  245. LCID lcid, DISPID *rgdispid),
  246. (riid, rgszNames, cNames, lcid, rgdispid))
  247. ACCESSIBILITY_FORWARD(Invoke,
  248. (DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags,
  249. DISPPARAMS *pdispparams, VARIANT *pvarResult,
  250. EXCEPINFO *pexcepinfo, UINT *puArgErr),
  251. (dispidMember, riid, lcid, wFlags,
  252. pdispparams, pvarResult,
  253. pexcepinfo, puArgErr))
  254. ACCESSIBILITY_FORWARD(get_accChildCount,
  255. (long *pChildCount),
  256. (pChildCount))
  257. ACCESSIBILITY_FORWARD(get_accChild,
  258. (VARIANT varChildIndex, IDispatch **ppdispChild),
  259. (varChildIndex, ppdispChild))
  260. ACCESSIBILITY_FORWARD(get_accName,
  261. (VARIANT varChild, BSTR *pszName),
  262. (varChild, pszName))
  263. ACCESSIBILITY_FORWARD(get_accValue,
  264. (VARIANT varChild, BSTR *pszValue),
  265. (varChild, pszValue))
  266. ACCESSIBILITY_FORWARD(get_accDescription,
  267. (VARIANT varChild, BSTR *pszDescription),
  268. (varChild, pszDescription))
  269. ACCESSIBILITY_FORWARD(get_accRole,
  270. (VARIANT varChild, VARIANT *pvarRole),
  271. (varChild, pvarRole))
  272. ACCESSIBILITY_FORWARD(get_accState,
  273. (VARIANT varChild, VARIANT *pvarState),
  274. (varChild, pvarState))
  275. ACCESSIBILITY_FORWARD(get_accHelp,
  276. (VARIANT varChild, BSTR *pszHelp),
  277. (varChild, pszHelp))
  278. ACCESSIBILITY_FORWARD(get_accHelpTopic,
  279. (BSTR *pszHelpFile, VARIANT varChild, long *pidTopic),
  280. (pszHelpFile, varChild, pidTopic))
  281. ACCESSIBILITY_FORWARD(get_accKeyboardShortcut,
  282. (VARIANT varChild, BSTR *pszKeyboardShortcut),
  283. (varChild, pszKeyboardShortcut))
  284. ACCESSIBILITY_FORWARD(get_accFocus,
  285. (VARIANT *pvarFocusChild),
  286. (pvarFocusChild))
  287. ACCESSIBILITY_FORWARD(get_accSelection,
  288. (VARIANT *pvarSelectedChildren),
  289. (pvarSelectedChildren))
  290. ACCESSIBILITY_FORWARD(get_accDefaultAction,
  291. (VARIANT varChild, BSTR *pszDefaultAction),
  292. (varChild, pszDefaultAction))
  293. ACCESSIBILITY_FORWARD(accSelect,
  294. (long flagsSelect, VARIANT varChild),
  295. (flagsSelect, varChild))
  296. ACCESSIBILITY_FORWARD(accLocation,
  297. (long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varChild),
  298. (pxLeft, pyTop, pcxWidth, pcyHeight, varChild))
  299. ACCESSIBILITY_FORWARD(accNavigate,
  300. (long navDir, VARIANT varStart, VARIANT *pvarEndUpAt),
  301. (navDir, varStart, pvarEndUpAt))
  302. ACCESSIBILITY_FORWARD(accHitTest,
  303. (long xLeft, long yTop, VARIANT *pvarChildAtPoint),
  304. (xLeft, yTop, pvarChildAtPoint))
  305. ACCESSIBILITY_FORWARD(accDoDefaultAction,
  306. (VARIANT varChild),
  307. (varChild));
  308. ACCESSIBILITY_FORWARD(put_accName,
  309. (VARIANT varChild, BSTR szName),
  310. (varChild, szName))
  311. ACCESSIBILITY_FORWARD(put_accValue,
  312. (VARIANT varChild, BSTR pszValue),
  313. (varChild, pszValue));
  314. LRESULT CALLBACK CAccessible::s_SubclassProc(
  315. HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
  316. UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
  317. {
  318. CAccessible *self = reinterpret_cast<CAccessible *>(dwRefData);
  319. switch (uMsg)
  320. {
  321. case WM_GETOBJECT:
  322. if (lParam == OBJID_CLIENT) {
  323. HRESULT hr;
  324. // Create the accessibility object for the inner listview if we haven't already
  325. // We forward nearly all calls to the inner IAccessible.
  326. if (!self->_paccInner)
  327. {
  328. hr = CreateStdAccessibleObject(hwnd, (DWORD)lParam, IID_PPV_ARG(IAccessible, &self->_paccInner));
  329. } else {
  330. hr = S_OK;
  331. }
  332. if (SUCCEEDED(hr))
  333. {
  334. return LresultFromObject(IID_IAccessible, wParam, SAFECAST(self, IAccessible *));
  335. } else {
  336. return hr;
  337. }
  338. };
  339. break;
  340. case WM_NCDESTROY:
  341. RemoveWindowSubclass(hwnd, s_SubclassProc, 0);
  342. break;
  343. }
  344. return DefSubclassProc(hwnd, uMsg, wParam, lParam);
  345. }
  346. HRESULT CAccessible::GetRoleString(DWORD dwRole, BSTR *pbsOut)
  347. {
  348. *pbsOut = NULL;
  349. WCHAR szBuf[MAX_PATH];
  350. if (GetRoleTextW(dwRole, szBuf, ARRAYSIZE(szBuf)))
  351. {
  352. *pbsOut = SysAllocString(szBuf);
  353. }
  354. return *pbsOut ? S_OK : E_OUTOFMEMORY;
  355. }
  356. HRESULT CAccessible::CreateAcceleratorBSTR(TCHAR tch, BSTR *pbsOut)
  357. {
  358. TCHAR sz[2] = { tch, 0 };
  359. *pbsOut = SysAllocString(sz);
  360. return *pbsOut ? S_OK : E_OUTOFMEMORY;
  361. }