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.

707 lines
21 KiB

  1. #include "shellprv.h"
  2. #include "util.h"
  3. #include "idlcomm.h"
  4. #include <uxtheme.h>
  5. #include <tmschema.h>
  6. // shdocvw and browseui share brutil and menubands need it too
  7. // unfortunately shell32 isnt set up quite like shdocvw and browseui so
  8. // these have to be hacked in a little
  9. #define MAX_BROWSER_WINDOW_TITLE 128
  10. #define g_fRunningOnNT TRUE
  11. #define InitClipboardFormats IDLData_InitializeClipboardFormats
  12. #define g_cfFileDescA g_cfFileGroupDescriptorA
  13. #define g_cfFileDescW g_cfFileGroupDescriptorW
  14. #define g_cfURL g_cfShellURL
  15. #define PVAREMPTY ((VARIANT*)&c_vaEmpty)
  16. #define NO_MLUI_IN_SHELL32
  17. #include "..\inc\brutil.cpp"
  18. const VARIANT c_vaEmpty = {0};
  19. HRESULT QueryService_SID_IBandProxy(IUnknown * punkParent, REFIID riid, IBandProxy ** ppbp, void **ppvObj)
  20. {
  21. HRESULT hr = E_FAIL;
  22. if (ppbp)
  23. {
  24. if (NULL == (*ppbp))
  25. hr = IUnknown_QueryService(punkParent, SID_IBandProxy, IID_PPV_ARG(IBandProxy, ppbp));
  26. if (*ppbp && ppvObj)
  27. hr = (*ppbp)->QueryInterface(riid, ppvObj); // They already have the object.
  28. }
  29. return hr;
  30. }
  31. HRESULT CreateIBandProxyAndSetSite(IUnknown * punkParent, REFIID riid, IBandProxy ** ppbp, void **ppvObj)
  32. {
  33. ASSERT(ppbp);
  34. HRESULT hr = CoCreateInstance(CLSID_BandProxy, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IBandProxy, ppbp));
  35. if (SUCCEEDED(hr))
  36. {
  37. // Set the site
  38. ASSERT(*ppbp);
  39. (*ppbp)->SetSite(punkParent);
  40. if (ppvObj)
  41. hr = (*ppbp)->QueryInterface(riid, ppvObj);
  42. }
  43. else
  44. {
  45. if (ppvObj)
  46. *ppvObj = NULL;
  47. }
  48. return hr;
  49. }
  50. typedef struct tagINIPAIR
  51. {
  52. DWORD dwFlags;
  53. LPCTSTR pszSection;
  54. }
  55. INIPAIR;
  56. const INIPAIR c_aIniPairs[] =
  57. {
  58. EICH_KINET, TEXT("Software\\Microsoft\\Internet Explorer"),
  59. EICH_KINETMAIN, TEXT("Software\\Microsoft\\Internet Explorer\\Main"),
  60. EICH_KWIN, TEXT("Software\\Microsoft\\Windows\\CurrentVersion"),
  61. EICH_KWINEXPLORER, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"),
  62. EICH_KWINEXPLSMICO, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\SmallIcons"),
  63. EICH_KWINPOLICY, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies"),
  64. EICH_SSAVETASKBAR, TEXT("SaveTaskbar"),
  65. EICH_SWINDOWMETRICS, TEXT("WindowMetrics"),
  66. EICH_SSHELLMENU, TEXT("ShellMenu"),
  67. EICH_SPOLICY, TEXT("Policy"),
  68. EICH_SWINDOWS, TEXT("Windows"),
  69. };
  70. DWORD SHIsExplorerIniChange(WPARAM wParam, LPARAM lParam)
  71. {
  72. DWORD dwFlags = 0;
  73. if (lParam == 0)
  74. {
  75. if (wParam == 0)
  76. {
  77. dwFlags = EICH_UNKNOWN;
  78. }
  79. }
  80. else
  81. {
  82. //
  83. // In the wacky world of browseui, UNICODE-ANSI doesn't vary from
  84. // window to window. Instead, on NT browseui registers all windows
  85. // UNICODE, while on 9x user browseui registers all windows ANSI.
  86. //
  87. USES_CONVERSION;
  88. LPCTSTR pszSection = W2CT((LPCWSTR)lParam);
  89. for (int i = 0; !dwFlags && i < ARRAYSIZE(c_aIniPairs); i++)
  90. {
  91. if (StrCmpI(pszSection, c_aIniPairs[i].pszSection) == 0)
  92. {
  93. dwFlags = c_aIniPairs[i].dwFlags;
  94. }
  95. }
  96. }
  97. return dwFlags;
  98. }
  99. ULONG RegisterNotify(HWND hwnd, UINT nMsg, LPCITEMIDLIST pidl, DWORD dwEvents, UINT uFlags, BOOL fRecursive)
  100. {
  101. SHChangeNotifyEntry fsne;
  102. uFlags |= SHCNRF_NewDelivery;
  103. fsne.fRecursive = fRecursive;
  104. fsne.pidl = pidl;
  105. return SHChangeNotifyRegister(hwnd, uFlags, dwEvents, nMsg, 1, &fsne);
  106. }
  107. BOOL GetInfoTipEx(IShellFolder* psf, DWORD dwFlags, LPCITEMIDLIST pidl, LPTSTR pszText, int cchTextMax)
  108. {
  109. BOOL fRet = FALSE;
  110. *pszText = 0; // empty for failure
  111. if (pidl)
  112. {
  113. IQueryInfo *pqi;
  114. if (SUCCEEDED(psf->GetUIObjectOf(NULL, 1, &pidl, IID_X_PPV_ARG(IQueryInfo, NULL, &pqi))))
  115. {
  116. WCHAR *pwszTip;
  117. pqi->GetInfoTip(dwFlags, &pwszTip);
  118. if (pwszTip)
  119. {
  120. fRet = TRUE;
  121. SHUnicodeToTChar(pwszTip, pszText, cchTextMax);
  122. SHFree(pwszTip);
  123. }
  124. pqi->Release();
  125. }
  126. }
  127. return fRet;
  128. }
  129. BOOL GetInfoTip(IShellFolder* psf, LPCITEMIDLIST pidl, LPTSTR pszText, int cchTextMax)
  130. {
  131. return GetInfoTipEx(psf, 0, pidl, pszText, cchTextMax);
  132. }
  133. BOOL IsBrowsableShellExt(LPCITEMIDLIST pidl)
  134. {
  135. DWORD cb;
  136. LPCTSTR pszExt;
  137. TCHAR szFile[MAX_PATH];
  138. TCHAR szProgID[80]; // From ..\shell32\fstreex.c
  139. TCHAR szCLSID[GUIDSTR_MAX], szCATID[GUIDSTR_MAX];
  140. TCHAR szKey[GUIDSTR_MAX * 4];
  141. HKEY hkeyProgID = NULL;
  142. BOOL fRet = FALSE;
  143. for (;;)
  144. {
  145. // Make sure we have a file extension
  146. if (
  147. !SHGetPathFromIDList(pidl, szFile)
  148. ||
  149. ((pszExt = PathFindExtension(szFile)) == NULL)
  150. ||
  151. (pszExt[0] != TEXT('.'))
  152. )
  153. {
  154. break;
  155. }
  156. // Get the ProgID.
  157. cb = sizeof(szProgID);
  158. if (
  159. (SHGetValue(HKEY_CLASSES_ROOT, pszExt, NULL, NULL, szProgID, &cb) != ERROR_SUCCESS)
  160. ||
  161. (RegOpenKey(HKEY_CLASSES_ROOT, szProgID, &hkeyProgID) != ERROR_SUCCESS)
  162. )
  163. {
  164. break;
  165. }
  166. // From the ProgID, get the CLSID.
  167. cb = sizeof(szCLSID);
  168. if (SHGetValue(hkeyProgID, TEXT("CLSID"), NULL, NULL, szCLSID, &cb) != ERROR_SUCCESS)
  169. break;
  170. // Construct the registry key that detects if
  171. // a CLSID is a member of a CATID.
  172. SHStringFromGUID(CATID_BrowsableShellExt, szCATID, ARRAYSIZE(szCATID));
  173. wnsprintf(szKey, ARRAYSIZE(szKey), TEXT("CLSID\\%s\\Implemented Categories\\%s"),
  174. szCLSID, szCATID);
  175. // See if it's there.
  176. cb = 0;
  177. if (SHGetValue(HKEY_CLASSES_ROOT, szKey, NULL, NULL, NULL, &cb) != ERROR_SUCCESS)
  178. break;
  179. fRet = TRUE;
  180. break;
  181. }
  182. if (hkeyProgID != NULL)
  183. RegCloseKey(hkeyProgID);
  184. return fRet;
  185. }
  186. void OpenFolderPidl(LPCITEMIDLIST pidl)
  187. {
  188. SHELLEXECUTEINFO shei = { 0 };
  189. shei.cbSize = sizeof(shei);
  190. shei.fMask = SEE_MASK_INVOKEIDLIST;
  191. shei.nShow = SW_SHOWNORMAL;
  192. shei.lpIDList = (LPITEMIDLIST)pidl;
  193. ShellExecuteEx(&shei);
  194. }
  195. // As perf, share IShellLink implementations between bands and ask
  196. // the bandsite for an implementation. Don't rely on the bandsite
  197. // because you never know who will host us in the future. (And bandsite
  198. // can change to not have us hosted at save/load time. Ex: it doesn't
  199. // set our site before loading us from the stream, which sounds buggy.)
  200. //
  201. HRESULT SavePidlAsLink(IUnknown* punkSite, IStream *pstm, LPCITEMIDLIST pidl)
  202. {
  203. HRESULT hr = E_FAIL;
  204. IShellLinkA* psl;
  205. if (punkSite)
  206. hr = IUnknown_QueryService(punkSite, IID_IBandSite, IID_PPV_ARG(IShellLinkA, &psl));
  207. if (FAILED(hr))
  208. hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IShellLinkA, &psl));
  209. if (SUCCEEDED(hr))
  210. {
  211. IPersistStream *pps;
  212. hr = psl->QueryInterface(IID_PPV_ARG(IPersistStream, &pps));
  213. if (EVAL(SUCCEEDED(hr)))
  214. {
  215. ASSERT(pidl);
  216. psl->SetIDList(pidl);
  217. hr = pps->Save(pstm, FALSE);
  218. pps->Release();
  219. }
  220. psl->Release();
  221. }
  222. return hr;
  223. }
  224. HRESULT LoadPidlAsLink(IUnknown* punkSite, IStream *pstm, LPITEMIDLIST *ppidl)
  225. {
  226. IShellLinkA* psl;
  227. HRESULT hr = IUnknown_QueryService(punkSite, IID_IBandSite, IID_PPV_ARG(IShellLinkA, &psl));
  228. if (FAILED(hr))
  229. hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IShellLinkA, &psl));
  230. if (SUCCEEDED(hr))
  231. {
  232. IPersistStream *pps;
  233. hr = psl->QueryInterface(IID_PPV_ARG(IPersistStream, &pps));
  234. if (EVAL(SUCCEEDED(hr)))
  235. {
  236. hr = pps->Load(pstm);
  237. if (EVAL(SUCCEEDED(hr)))
  238. {
  239. hr = psl->GetIDList(ppidl);
  240. // Don't make me resolve the link because it's soo slow because
  241. // it often loads 80k of networking dlls.
  242. if (!EVAL(SUCCEEDED(hr)))
  243. {
  244. hr = psl->Resolve(NULL, SLR_NOUPDATE | SLR_NO_UI);
  245. if (EVAL(SUCCEEDED(hr)))
  246. hr = psl->GetIDList(ppidl);
  247. }
  248. hr = *ppidl ? S_OK : E_FAIL;
  249. }
  250. pps->Release();
  251. }
  252. psl->Release();
  253. }
  254. return hr;
  255. }
  256. // Review chrisny: this can be moved into an object easily to handle generic droptarget, dropcursor
  257. // , autoscrool, etc. . .
  258. void _DragEnter(HWND hwndTarget, const POINTL ptStart, IDataObject *pdtObject)
  259. {
  260. RECT rc;
  261. POINT pt;
  262. GetWindowRect(hwndTarget, &rc);
  263. //
  264. // If hwndTarget is RTL mirrored, then measure the
  265. // the client point from the visual right edge
  266. // (near edge in RTL mirrored windows). [samera]
  267. //
  268. if (IS_WINDOW_RTL_MIRRORED(hwndTarget))
  269. pt.x = rc.right - ptStart.x;
  270. else
  271. pt.x = ptStart.x - rc.left;
  272. pt.y = ptStart.y - rc.top;
  273. DAD_DragEnterEx2(hwndTarget, pt, pdtObject);
  274. return;
  275. }
  276. void _DragMove(HWND hwndTarget, const POINTL ptStart)
  277. {
  278. RECT rc;
  279. POINT pt;
  280. GetWindowRect(hwndTarget, &rc);
  281. //
  282. // If hwndTarget is RTL mirrored, then measure the
  283. // the client point from the visual right edge
  284. // (near edge in RTL mirrored windows). [samera]
  285. //
  286. if (IS_WINDOW_RTL_MIRRORED(hwndTarget))
  287. pt.x = rc.right - ptStart.x;
  288. else
  289. pt.x = ptStart.x - rc.left;
  290. pt.y = ptStart.y - rc.top;
  291. DAD_DragMove(pt);
  292. return;
  293. }
  294. // Can we browse or navigate to this pidl? If not, need
  295. BOOL ILIsBrowsable(LPCITEMIDLIST pidl, BOOL *pfIsFolder)
  296. {
  297. if (!pidl)
  298. return FALSE;
  299. DWORD dwAttributes = SFGAO_FOLDER | SFGAO_BROWSABLE;
  300. HRESULT hr = IEGetAttributesOf(pidl, &dwAttributes);
  301. if (pfIsFolder && SUCCEEDED(hr))
  302. *pfIsFolder = dwAttributes & SFGAO_FOLDER;
  303. return SUCCEEDED(hr) && (dwAttributes & (SFGAO_FOLDER | SFGAO_BROWSABLE));
  304. }
  305. // gets a target pidl given a name space item. typically this is a .lnk or .url file
  306. //
  307. // in:
  308. // psf shell folder for item
  309. // pidl item relative to psf, single level
  310. //
  311. // in/out
  312. // pdwAttribs [optional] attributes mask to filter on (returned).
  313. // must be initalized
  314. //
  315. //
  316. // returns
  317. // *ppidl the target pidl
  318. // *pdwAttribs [optional] attributes of the source object
  319. STDAPI SHGetNavigateTarget(IShellFolder *psf, LPCITEMIDLIST pidl, LPITEMIDLIST *ppidl, DWORD *pdwAttribs)
  320. {
  321. ASSERT(IS_VALID_CODE_PTR(psf, IShellFolder));
  322. ASSERT(IS_VALID_PIDL(pidl));
  323. ASSERT(NULL == pdwAttribs || IS_VALID_WRITE_PTR(pdwAttribs, DWORD));
  324. ASSERT(ILFindLastID(pidl) == pidl); // must be single level PIDL
  325. *ppidl = NULL; // assume failure
  326. DWORD dwAttribs = SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_LINK | SFGAO_BROWSABLE;
  327. if (pdwAttribs)
  328. dwAttribs |= *pdwAttribs;
  329. HRESULT hr = psf->GetAttributesOf(1, &pidl, &dwAttribs);
  330. if (SUCCEEDED(hr))
  331. {
  332. // first try the most efficient way
  333. IShellLinkA *psl; // "A" so this works on Win95
  334. hr = psf->GetUIObjectOf(NULL, 1, &pidl, IID_X_PPV_ARG(IShellLinkA, NULL, &psl));
  335. if (SUCCEEDED(hr))
  336. {
  337. hr = psl->GetIDList(ppidl);
  338. psl->Release();
  339. }
  340. // this is for .lnk and .url files that don't register properly
  341. if (FAILED(hr) && (dwAttribs & (SFGAO_FILESYSTEM | SFGAO_LINK)) == (SFGAO_FILESYSTEM | SFGAO_LINK))
  342. {
  343. TCHAR szPath[MAX_PATH];
  344. hr = GetPathForItem(psf, pidl, szPath, NULL);
  345. if (SUCCEEDED(hr))
  346. hr = GetLinkTargetIDList(szPath, NULL, 0, ppidl);
  347. }
  348. // .doc or .html. return the pidl for this.
  349. // (fully qualify against the folder pidl)
  350. if (FAILED(hr) && (dwAttribs & SFGAO_BROWSABLE))
  351. {
  352. LPITEMIDLIST pidlFolder;
  353. hr = SHGetIDListFromUnk(psf, &pidlFolder);
  354. if (SUCCEEDED(hr))
  355. {
  356. *ppidl = ILCombine(pidlFolder, pidl); // navigate to this thing...
  357. hr = *ppidl ? S_OK : E_OUTOFMEMORY;
  358. ILFree(pidlFolder);
  359. }
  360. }
  361. // Callers of SHGetNavigateTarget assume that the returned pidl
  362. // is navigatable (SFGAO_FOLDER or SFGAO_BROWSER), which isn't
  363. // the case for a link (it could be a link to an exe).
  364. //
  365. if (SUCCEEDED(hr) && !ILIsBrowsable(*ppidl, NULL))
  366. {
  367. ILFree(*ppidl);
  368. *ppidl = NULL;
  369. hr = E_FAIL;
  370. }
  371. if (SUCCEEDED(hr) && pdwAttribs)
  372. *pdwAttribs = dwAttribs;
  373. }
  374. return hr;
  375. }
  376. STDAPI SHNavigateToFavorite(IShellFolder* psf, LPCITEMIDLIST pidl, IUnknown* punkSite, DWORD dwFlags)
  377. {
  378. HRESULT hr = S_FALSE;
  379. TCHAR szPath[MAX_PATH];
  380. // Can we navigate to this favorite?
  381. BOOL fNavigateDone = SUCCEEDED(GetPathForItem(psf, pidl, szPath, NULL)) &&
  382. SUCCEEDED(NavFrameWithFile(szPath, punkSite));
  383. if (fNavigateDone)
  384. return S_OK;
  385. LPITEMIDLIST pidlGoto;
  386. ASSERT(!(dwFlags & (SBSP_NEWBROWSER | SBSP_SAMEBROWSER)));
  387. if (SUCCEEDED(SHGetNavigateTarget(psf, pidl, &pidlGoto, NULL)))
  388. {
  389. IShellBrowser* psb;
  390. if (SUCCEEDED(IUnknown_QueryService(punkSite, SID_STopLevelBrowser,
  391. IID_PPV_ARG(IShellBrowser, &psb))))
  392. {
  393. hr = psb->BrowseObject(pidlGoto, dwFlags | SBSP_SAMEBROWSER);
  394. psb->Release();
  395. }
  396. ILFree(pidlGoto);
  397. }
  398. return hr;
  399. }
  400. STDAPI SHGetTopBrowserWindow(IUnknown* punk, HWND* phwnd)
  401. {
  402. IOleWindow* pOleWindow;
  403. HRESULT hr = IUnknown_QueryService(punk, SID_STopLevelBrowser, IID_PPV_ARG(IOleWindow, &pOleWindow));
  404. if (SUCCEEDED(hr))
  405. {
  406. hr = pOleWindow->GetWindow(phwnd);
  407. pOleWindow->Release();
  408. }
  409. return hr;
  410. }
  411. void SHOutlineRect(HDC hdc, const RECT* prc, COLORREF cr)
  412. {
  413. RECT rc;
  414. COLORREF clrSave = SetBkColor(hdc, cr);
  415. //top
  416. rc.left = prc->left;
  417. rc.top = prc->top;
  418. rc.right = prc->right;
  419. rc.bottom = prc->top + 1;
  420. ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
  421. //left
  422. rc.left = prc->left;
  423. rc.top = prc->top;
  424. rc.right = prc->left + 1;
  425. rc.bottom = prc->bottom;
  426. ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
  427. //right
  428. rc.left = prc->right - 1;
  429. rc.top = prc->top;
  430. rc.right = prc->right;
  431. rc.bottom = prc->bottom;
  432. ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
  433. // bottom
  434. rc.left = prc->left;
  435. rc.top = prc->bottom - 1;
  436. rc.right = prc->right;
  437. rc.bottom = prc->bottom;
  438. ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
  439. SetBkColor(hdc, clrSave);
  440. }
  441. STDAPI NavigateToPIDL(IWebBrowser2* pwb, LPCITEMIDLIST pidl)
  442. {
  443. ASSERT(pwb);
  444. ASSERT(pidl);
  445. VARIANT varThePidl;
  446. HRESULT hr = InitVariantFromIDList(&varThePidl, pidl);
  447. if (SUCCEEDED(hr))
  448. {
  449. hr = pwb->Navigate2(&varThePidl, PVAREMPTY, PVAREMPTY, PVAREMPTY, PVAREMPTY);
  450. VariantClear(&varThePidl); // Needed to free the copy of the PIDL in varThePidl.
  451. }
  452. return hr;
  453. }
  454. HRESULT Channels_OpenBrowser(IWebBrowser2 **ppwb, BOOL fInPlace)
  455. {
  456. HRESULT hr;
  457. IWebBrowser2* pwb;
  458. if (fInPlace)
  459. {
  460. ASSERT(ppwb && *ppwb != NULL);
  461. pwb = *ppwb;
  462. hr = S_OK;
  463. }
  464. else
  465. {
  466. hr = CoCreateInstance(CLSID_InternetExplorer, NULL, CLSCTX_LOCAL_SERVER, IID_PPV_ARG(IWebBrowser2, &pwb));
  467. }
  468. if (SUCCEEDED(hr))
  469. {
  470. // Don't special case full-screen mode for channels post IE4. Use the
  471. // browser's full screen setting.
  472. //
  473. //BOOL fTheater = SHRegGetBoolUSValue(TEXT("Software\\Microsoft\\Internet Explorer\\Channels"),
  474. BOOL fTheater = SHRegGetBoolUSValue(TEXT("Software\\Microsoft\\Internet Explorer\\Main"),
  475. TEXT("FullScreen"), FALSE, FALSE);
  476. pwb->put_TheaterMode( fTheater ? VARIANT_TRUE : VARIANT_FALSE);
  477. pwb->put_Visible(VARIANT_TRUE);
  478. if (!SHRestricted2(REST_NoChannelUI, NULL, 0))
  479. {
  480. SA_BSTRGUID strGuid;
  481. VARIANT vaGuid;
  482. InitFakeBSTR(&strGuid, CLSID_FavBand);
  483. vaGuid.vt = VT_BSTR;
  484. vaGuid.bstrVal = strGuid.wsz;
  485. pwb->ShowBrowserBar(&vaGuid, PVAREMPTY, PVAREMPTY);
  486. }
  487. // don't release, we're going to return pwb.
  488. }
  489. if (ppwb)
  490. *ppwb = pwb;
  491. else if (pwb)
  492. pwb->Release();
  493. return hr;
  494. }
  495. //
  496. // Just like TB_GETBUTTONSIZE except that theme borders are subtracted out.
  497. //
  498. LRESULT TB_GetButtonSizeWithoutThemeBorder(HWND hwndTB, HTHEME hThemeParent)
  499. {
  500. LRESULT lButtonSize = SendMessage(hwndTB, TB_GETBUTTONSIZE, 0, 0L);
  501. if (hThemeParent)
  502. {
  503. HTHEME hTheme = OpenThemeData(hwndTB, L"Toolbar");
  504. if (hTheme)
  505. {
  506. RECT rc = { 0, 0, 0, 0 };
  507. if (SUCCEEDED(GetThemeBackgroundExtent(hTheme, NULL, TP_BUTTON, TS_NORMAL, &rc, &rc)))
  508. {
  509. lButtonSize = MAKELONG(LOWORD(lButtonSize) - RECTWIDTH(rc),
  510. HIWORD(lButtonSize) - RECTHEIGHT(rc));
  511. }
  512. CloseThemeData(hTheme);
  513. }
  514. }
  515. return lButtonSize;
  516. }
  517. #ifdef DEBUG
  518. extern "C" void DumpMsg(LPCTSTR pszLabel, MSG * pmsg)
  519. {
  520. ASSERT(IS_VALID_STRING_PTR(pszLabel, -1));
  521. ASSERT(pmsg);
  522. switch (pmsg->message)
  523. {
  524. case WM_LBUTTONDOWN:
  525. TraceMsg(TF_ALWAYS, "%s: msg = WM_LBUTTONDOWN hwnd = %#08lx x = %d y = %d",
  526. pszLabel, pmsg->hwnd, pmsg->pt.x, pmsg->pt.y);
  527. TraceMsg(TF_ALWAYS, " keys = %#04lx x = %d y = %d",
  528. pmsg->wParam, LOWORD(pmsg->lParam), HIWORD(pmsg->lParam));
  529. break;
  530. case WM_LBUTTONUP:
  531. TraceMsg(TF_ALWAYS, "%s: msg = WM_LBUTTONUP hwnd = %#08lx x = %d y = %d",
  532. pszLabel, pmsg->hwnd, pmsg->pt.x, pmsg->pt.y);
  533. TraceMsg(TF_ALWAYS, " keys = %#04lx x = %d y = %d",
  534. pmsg->wParam, LOWORD(pmsg->lParam), HIWORD(pmsg->lParam));
  535. break;
  536. case WM_KEYDOWN:
  537. case WM_SYSKEYDOWN:
  538. case WM_KEYUP:
  539. case WM_SYSKEYUP:
  540. BLOCK
  541. {
  542. LPTSTR pcsz = TEXT("(unknown)");
  543. switch (pmsg->message)
  544. {
  545. STRING_CASE(WM_KEYDOWN);
  546. STRING_CASE(WM_SYSKEYDOWN);
  547. STRING_CASE(WM_KEYUP);
  548. STRING_CASE(WM_SYSKEYUP);
  549. }
  550. TraceMsg(TF_ALWAYS, "%s: msg = %s hwnd = %#08lx",
  551. pszLabel, pcsz, pmsg->hwnd);
  552. TraceMsg(TF_ALWAYS, " vk = %#04lx count = %u flags = %#04lx",
  553. pmsg->wParam, LOWORD(pmsg->lParam), HIWORD(pmsg->lParam));
  554. }
  555. break;
  556. case WM_CHAR:
  557. case WM_SYSCHAR:
  558. BLOCK
  559. {
  560. LPTSTR pcsz = TEXT("(unknown)");
  561. switch (pmsg->message)
  562. {
  563. STRING_CASE(WM_CHAR);
  564. STRING_CASE(WM_SYSCHAR);
  565. }
  566. TraceMsg(TF_ALWAYS, "%s: msg = %s hwnd = %#08lx",
  567. pszLabel, pcsz, pmsg->hwnd);
  568. TraceMsg(TF_ALWAYS, " char = '%c' count = %u flags = %#04lx",
  569. pmsg->wParam, LOWORD(pmsg->lParam), HIWORD(pmsg->lParam));
  570. }
  571. break;
  572. case WM_MOUSEMOVE:
  573. #if 0
  574. TraceMsg(TF_ALWAYS, "%s: msg = WM_MOUSEMOVE hwnd = %#08lx x=%d y=%d",
  575. pszLabel, pmsg->hwnd, LOWORD(pmsg->lParam), HIWORD(pmsg->lParam));
  576. #endif
  577. break;
  578. case WM_TIMER:
  579. #if 0
  580. TraceMsg(TF_ALWAYS, "%s: msg = WM_TIMER hwnd = %#08lx x = %d y = %d",
  581. pszLabel, pmsg->hwnd, pmsg->pt.x, pmsg->pt.y);
  582. TraceMsg(TF_ALWAYS, " id = %#08lx",
  583. pmsg->wParam);
  584. #endif
  585. break;
  586. case WM_MENUSELECT:
  587. TraceMsg(TF_ALWAYS, "%s: msg = WM_MENUSELECT hwnd = %#08lx x = %d y = %d",
  588. pszLabel, pmsg->hwnd, pmsg->pt.x, pmsg->pt.y);
  589. TraceMsg(TF_ALWAYS, " uItem = %#04lx flags = %#04lx hmenu = %#08lx",
  590. GET_WM_MENUSELECT_CMD(pmsg->wParam, pmsg->lParam),
  591. GET_WM_MENUSELECT_FLAGS(pmsg->wParam, pmsg->lParam),
  592. GET_WM_MENUSELECT_HMENU(pmsg->wParam, pmsg->lParam));
  593. break;
  594. default:
  595. if (WM_USER > pmsg->message)
  596. {
  597. TraceMsg(TF_ALWAYS, "%s: msg = %#04lx hwnd=%#04lx wP=%#08lx lP=%#08lx",
  598. pszLabel, pmsg->message, pmsg->hwnd, pmsg->wParam, pmsg->lParam);
  599. }
  600. break;
  601. }
  602. }
  603. #endif