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.

302 lines
7.3 KiB

  1. #include "bands.h"
  2. #define DM_PERSIST 0 // trace IPS::Load, ::Save, etc.
  3. #define DM_MENU 0 // menu code
  4. #define DM_FOCUS 0 // focus
  5. #define DM_FOCUS2 0 // like DM_FOCUS, but verbose
  6. //=================================================================
  7. // Implementation of CToolBand
  8. //=================================================================
  9. ULONG CToolBand::AddRef()
  10. {
  11. _cRef++;
  12. return _cRef;
  13. }
  14. ULONG CToolBand::Release()
  15. {
  16. ASSERT(_cRef > 0);
  17. _cRef--;
  18. if (_cRef > 0)
  19. return _cRef;
  20. delete this;
  21. return 0;
  22. }
  23. HRESULT CToolBand::QueryInterface(REFIID riid, void **ppvObj)
  24. {
  25. static const QITAB qit[] =
  26. {
  27. QITABENT(CToolBand, IDeskBand), // IID_IDeskBand
  28. QITABENTMULTI(CToolBand, IOleWindow, IDeskBand), // IID_IOleWindod
  29. QITABENTMULTI(CToolBand, IDockingWindow, IDeskBand), // IID_IDockingWindow
  30. QITABENT(CToolBand, IInputObject), // IID_IInputObject
  31. QITABENT(CToolBand, IOleCommandTarget), // IID_IOleCommandTarget
  32. QITABENT(CToolBand, IServiceProvider), // IID_IServiceProvider
  33. QITABENT(CToolBand, IPersistStream), // IID_IPersistStream
  34. QITABENTMULTI(CToolBand, IPersist, IPersistStream), // IID_IPersist
  35. QITABENT(CToolBand, IObjectWithSite), // IID_IObjectWithSite
  36. { 0 },
  37. };
  38. return QISearch(this, qit, riid, ppvObj);
  39. }
  40. // *** IOleCommandTarget methods ***
  41. HRESULT CToolBand::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext)
  42. {
  43. return E_NOTIMPL;
  44. }
  45. HRESULT CToolBand::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  46. {
  47. return E_NOTIMPL;
  48. }
  49. // *** IServiceProvider methods ***
  50. HRESULT CToolBand::QueryService(REFGUID guidService,
  51. REFIID riid, void **ppvObj)
  52. {
  53. return IUnknown_QueryService(_punkSite, guidService, riid, ppvObj);
  54. }
  55. // *** IOleWindow methods ***
  56. HRESULT CToolBand::GetWindow(HWND * lphwnd)
  57. {
  58. *lphwnd = _hwnd;
  59. if (*lphwnd)
  60. return S_OK;
  61. return E_FAIL;
  62. }
  63. // *** IInputObject methods ***
  64. HRESULT CToolBand::TranslateAcceleratorIO(LPMSG lpMsg)
  65. {
  66. return E_NOTIMPL;
  67. }
  68. HRESULT CToolBand::HasFocusIO()
  69. {
  70. HRESULT hres;
  71. HWND hwndFocus = GetFocus();
  72. hres = SHIsChildOrSelf(_hwnd, hwndFocus);
  73. ASSERT(hwndFocus != NULL || hres == S_FALSE);
  74. ASSERT(_hwnd != NULL || hres == S_FALSE);
  75. return hres;
  76. }
  77. HRESULT CToolBand::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
  78. {
  79. ASSERT(NULL == lpMsg || IS_VALID_WRITE_PTR(lpMsg, MSG));
  80. TraceMsg(DM_FOCUS, "ctb.uiaio(fActivate=%d) _fCanFocus=%d _hwnd=%x GF()=%x", fActivate, _fCanFocus, _hwnd, GetFocus());
  81. if (!_fCanFocus) {
  82. TraceMsg(DM_FOCUS, "ctb.uiaio: !_fCanFocus ret S_FALSE");
  83. return S_FALSE;
  84. }
  85. if (fActivate)
  86. {
  87. IUnknown_OnFocusChangeIS(_punkSite, SAFECAST(this, IInputObject*), TRUE);
  88. SetFocus(_hwnd);
  89. }
  90. return S_OK;
  91. }
  92. HRESULT CToolBand::ResizeBorderDW(LPCRECT prcBorder,
  93. IUnknown* punkToolbarSite,
  94. BOOL fReserved)
  95. {
  96. return S_OK;
  97. }
  98. HRESULT CToolBand::ShowDW(BOOL fShow)
  99. {
  100. return S_OK;
  101. }
  102. HRESULT CToolBand::SetSite(IUnknown *punkSite)
  103. {
  104. if (punkSite != _punkSite)
  105. {
  106. IUnknown_Set(&_punkSite, punkSite);
  107. IUnknown_GetWindow(_punkSite, &_hwndParent);
  108. }
  109. return S_OK;
  110. }
  111. HRESULT CToolBand::_BandInfoChanged()
  112. {
  113. VARIANTARG v = {0};
  114. VARIANTARG* pv = NULL;
  115. if (_dwBandID != (DWORD)-1)
  116. {
  117. v.vt = VT_I4;
  118. v.lVal = _dwBandID;
  119. pv = &v;
  120. }
  121. else
  122. {
  123. // if this fires, fix your band's GetBandInfo to set _dwBandID.
  124. // o.w. it's a *big* perf loss since we refresh *all* bands rather
  125. // than just yours.
  126. // do *not* remove this ASSERT, bad perf *is* a bug.
  127. ASSERT(_dwBandID != (DWORD)-1);
  128. }
  129. return IUnknown_Exec(_punkSite, &CGID_DeskBand, DBID_BANDINFOCHANGED, 0, pv, NULL);
  130. }
  131. // *** IPersistStream methods ***
  132. HRESULT CToolBand::IsDirty(void)
  133. {
  134. return S_FALSE; // never be dirty
  135. }
  136. HRESULT CToolBand::GetSizeMax(ULARGE_INTEGER *pcbSize)
  137. {
  138. return E_NOTIMPL;
  139. }
  140. CToolBand::CToolBand() : _cRef(1)
  141. {
  142. _dwBandID = (DWORD)-1;
  143. DllAddRef();
  144. }
  145. CToolBand::~CToolBand()
  146. {
  147. ASSERT(_hwnd == NULL); // CloseDW was called
  148. ASSERT(_punkSite == NULL); // SetSite(NULL) was called
  149. DllRelease();
  150. }
  151. HRESULT CToolBand::CloseDW(DWORD dw)
  152. {
  153. if (_hwnd)
  154. {
  155. DestroyWindow(_hwnd);
  156. _hwnd = NULL;
  157. }
  158. return S_OK;
  159. }
  160. //=================================================================
  161. // Implementation of CToolbarBand
  162. //=================================================================
  163. // Class for bands whose _hwnd is a toolbar control. Implements
  164. // functionality generic to all such bands (e.g. hottracking
  165. // behavior).
  166. //=================================================================
  167. HRESULT CToolbarBand::_PushChevron(BOOL bLast)
  168. {
  169. if (_dwBandID == (DWORD)-1)
  170. return E_UNEXPECTED;
  171. VARIANTARG v;
  172. v.vt = VT_I4;
  173. v.lVal = bLast ? DBPC_SELECTLAST : DBPC_SELECTFIRST;
  174. return IUnknown_Exec(_punkSite, &CGID_DeskBand, DBID_PUSHCHEVRON, _dwBandID, &v, NULL);
  175. }
  176. LRESULT CToolbarBand::_OnHotItemChange(LPNMTBHOTITEM pnmtb)
  177. {
  178. LRESULT lres = 0;
  179. if (!(pnmtb->dwFlags & (HICF_LEAVING | HICF_MOUSE)))
  180. {
  181. // check to see if new hot button is clipped. if it is,
  182. // then we pop down the chevron menu.
  183. RECT rc;
  184. GetClientRect(_hwnd, &rc);
  185. int iButton = (int)SendMessage(_hwnd, TB_COMMANDTOINDEX, pnmtb->idNew, 0);
  186. DWORD dwEdge = SHIsButtonObscured(_hwnd, &rc, iButton);
  187. if (dwEdge)
  188. {
  189. //
  190. // Only pop down the menu if the button is obscured
  191. // along the axis of the toolbar
  192. //
  193. BOOL fVertical = (ToolBar_GetStyle(_hwnd) & CCS_VERT);
  194. if ((fVertical && (dwEdge & (EDGE_TOP | EDGE_BOTTOM)))
  195. || (!fVertical && (dwEdge & (EDGE_LEFT | EDGE_RIGHT))))
  196. {
  197. // clear hot item
  198. SendMessage(_hwnd, TB_SETHOTITEM, -1, 0);
  199. // figure out whether to highlight first or last button in dd menu
  200. int cButtons = (int)SendMessage(_hwnd, TB_BUTTONCOUNT, 0, 0);
  201. BOOL bLast = (iButton == cButtons - 1);
  202. _PushChevron(bLast);
  203. lres = 1;
  204. }
  205. }
  206. }
  207. return lres;
  208. }
  209. LRESULT CToolbarBand::_OnNotify(LPNMHDR pnmh)
  210. {
  211. LRESULT lres = 0;
  212. switch (pnmh->code)
  213. {
  214. case TBN_HOTITEMCHANGE:
  215. lres = _OnHotItemChange((LPNMTBHOTITEM)pnmh);
  216. break;
  217. }
  218. return lres;
  219. }
  220. // *** IWinEventHandler methods ***
  221. HRESULT CToolbarBand::OnWinEvent(HWND hwnd, UINT dwMsg, WPARAM wParam, LPARAM lParam, LRESULT* plres)
  222. {
  223. HRESULT hres = S_OK;
  224. switch (dwMsg)
  225. {
  226. case WM_NOTIFY:
  227. *plres = _OnNotify((LPNMHDR)lParam);
  228. break;
  229. case WM_WININICHANGE:
  230. InvalidateRect(_hwnd, NULL, TRUE);
  231. _BandInfoChanged();
  232. break;
  233. }
  234. return hres;
  235. }
  236. HRESULT CToolbarBand::IsWindowOwner(HWND hwnd)
  237. {
  238. if (hwnd == _hwnd)
  239. return S_OK;
  240. else
  241. return S_FALSE;
  242. }