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.

287 lines
8.3 KiB

  1. #include "priv.h"
  2. #include "resource.h"
  3. #include "tbmenu.h"
  4. #include "isfband.h"
  5. #include "isfmenu.h"
  6. #include "util.h"
  7. #include "mluisupp.h"
  8. #define SMFORWARD(x) if (!_psm) { return E_FAIL; } else return _psm->x
  9. #define SUPERCLASS CMenuToolbarBase
  10. CToolbarMenu::CToolbarMenu(DWORD dwFlags, HWND hwndTB) :
  11. CMenuToolbarBase(NULL, dwFlags),
  12. _hwndSubject(hwndTB) // this is the toolbar that we are customizing
  13. {
  14. }
  15. void CToolbarMenu::GetSize(SIZE* psize)
  16. {
  17. ASSERT(_hwndMB);
  18. if (SendMessage(_hwndMB, TB_GETTEXTROWS, 0, 0) == 0) {
  19. // no text labels, so set a min width to make menu look
  20. // pretty. use min width of 4 * button width.
  21. LRESULT lButtonSize = SendMessage(_hwndMB, TB_GETBUTTONSIZE, 0, 0);
  22. LONG cxMin = 4 * LOWORD(lButtonSize);
  23. psize->cx = max(psize->cx, cxMin);
  24. }
  25. SUPERCLASS::GetSize(psize);
  26. }
  27. void CToolbarMenu::v_Show(BOOL fShow, BOOL fForceUpdate)
  28. {
  29. if (fShow)
  30. {
  31. _fClickHandled = FALSE;
  32. _FillToolbar();
  33. _pcmb->SetTracked(NULL); // Since hot item is NULL
  34. ToolBar_SetHotItem(_hwndMB, -1);
  35. if (fForceUpdate)
  36. v_UpdateButtons(TRUE);
  37. }
  38. }
  39. void CToolbarMenu::v_Close()
  40. {
  41. _UnsubclassWindow(_hwndMB);
  42. }
  43. void CToolbarMenu::v_UpdateButtons(BOOL fNegotiateSize)
  44. {
  45. }
  46. HRESULT CToolbarMenu::v_CallCBItem(int idtCmd, UINT dwMsg, WPARAM wParam, LPARAM lParam)
  47. {
  48. return S_OK;
  49. }
  50. HRESULT CToolbarMenu::v_GetState(int idtCmd, LPSMDATA psmd)
  51. {
  52. ASSERT(0);
  53. return E_NOTIMPL;
  54. }
  55. HRESULT CToolbarMenu::v_ExecItem(int idCmd)
  56. {
  57. HRESULT hres = E_FAIL;
  58. TraceMsg(TF_TBMENU, "CToolbarMenu::v_ExecItem \tidCmd: %d", idCmd);
  59. return hres;
  60. }
  61. void CToolbarMenu::CreateToolbar(HWND hwndParent)
  62. {
  63. if (!_hwndMB)
  64. {
  65. DWORD dwStyle = (WS_VISIBLE | WS_CHILD | TBSTYLE_FLAT |
  66. WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NODIVIDER |
  67. CCS_NOPARENTALIGN | CCS_NORESIZE | TBSTYLE_REGISTERDROP | TBSTYLE_TOOLTIPS);
  68. INT_PTR nRows = SendMessage(_hwndSubject, TB_GETTEXTROWS, 0, 0);
  69. if (nRows > 0)
  70. {
  71. // We have text labels; make it TBSTYLE_LIST. The base class will
  72. // set TBSTYLE_EX_VERTICAL for us.
  73. ASSERT(_fHorizInVerticalMB == FALSE);
  74. dwStyle |= TBSTYLE_LIST;
  75. }
  76. else
  77. {
  78. // No text labels; make it horizontal and TBSTYLE_WRAPABLE. Set
  79. // _fHorizInVerticalMB so that the base class does not try and set
  80. // TBSTYLE_EX_VERTICAL.
  81. _fHorizInVerticalMB = TRUE;
  82. dwStyle |= TBSTYLE_WRAPABLE;
  83. }
  84. _hwndMB = CreateWindowEx(WS_EX_TOOLWINDOW, TOOLBARCLASSNAME, TEXT("Menu"), dwStyle,
  85. 0, 0, 0, 0, hwndParent, (HMENU) FCIDM_TOOLBAR, HINST_THISDLL, NULL);
  86. if (!_hwndMB)
  87. {
  88. TraceMsg(TF_TBMENU, "CToolbarMenu::CreateToolbar: Failed to Create Toolbar");
  89. return;
  90. }
  91. HWND hwndTT = (HWND)SendMessage(_hwndMB, TB_GETTOOLTIPS, 0, 0);
  92. SHSetWindowBits(hwndTT, GWL_STYLE, TTS_ALWAYSTIP, TTS_ALWAYSTIP);
  93. SendMessage(_hwndMB, TB_BUTTONSTRUCTSIZE, SIZEOF(TBBUTTON), 0);
  94. SendMessage(_hwndMB, TB_SETMAXTEXTROWS, nRows, 0);
  95. SendMessage(_hwndMB, CCM_SETVERSION, COMCTL32_VERSION, 0);
  96. SendMessage(_hwndMB, TB_SETEXTENDEDSTYLE, TBSTYLE_EX_DRAWDDARROWS, TBSTYLE_EX_DRAWDDARROWS);
  97. int cPimgs = (int)SendMessage(_hwndSubject, TB_GETIMAGELISTCOUNT, 0, 0);
  98. for (int i = 0; i < cPimgs; i++)
  99. {
  100. HIMAGELIST himl = (HIMAGELIST)SendMessage(_hwndSubject, TB_GETIMAGELIST, i, 0);
  101. SendMessage(_hwndMB, TB_SETIMAGELIST, i, (LPARAM)himl);
  102. HIMAGELIST himlHot = (HIMAGELIST)SendMessage(_hwndSubject, TB_GETHOTIMAGELIST, i, 0);
  103. SendMessage(_hwndMB, TB_SETHOTIMAGELIST, i, (LPARAM)himlHot);
  104. }
  105. _SubclassWindow(_hwndMB);
  106. // Set the format to ANSI
  107. ToolBar_SetUnicodeFormat(_hwndMB, 0);
  108. CMenuToolbarBase::CreateToolbar(hwndParent);
  109. }
  110. else if (GetParent(_hwndMB) != hwndParent)
  111. {
  112. ::SetParent(_hwndMB, hwndParent);
  113. }
  114. }
  115. LRESULT CToolbarMenu::_DefWindowProc(HWND hwnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
  116. {
  117. LRESULT lRes = CMenuToolbarBase::_DefWindowProcMB(hwnd, uMessage, wParam, lParam);
  118. if (lRes == 0)
  119. lRes = CNotifySubclassWndProc::_DefWindowProc(hwnd, uMessage, wParam, lParam);
  120. return lRes;
  121. }
  122. #define MAXLEN 256
  123. void CToolbarMenu::_FillToolbar()
  124. {
  125. RECT rcTB;
  126. TCHAR pszBuf[MAXLEN+1];
  127. LPTSTR psz;
  128. TBBUTTON tb;
  129. INT_PTR i, iCount;
  130. iCount = SendMessage(_hwndSubject, TB_BUTTONCOUNT, 0, 0L);
  131. GetClientRect(_hwndSubject, &rcTB);
  132. for (i = 0; i < iCount; i++) {
  133. if (SHIsButtonObscured(_hwndSubject, &rcTB, i)) {
  134. SendMessage(_hwndSubject, TB_GETBUTTON, i, (LPARAM)&tb);
  135. if (!(tb.fsStyle & BTNS_SEP)) {
  136. // autosize buttons look ugly here
  137. tb.fsStyle &= ~BTNS_AUTOSIZE;
  138. // need to rip off wrap bit; new toolbar will
  139. // figure out where wrapping should happen
  140. tb.fsState &= ~TBSTATE_WRAP;
  141. if (tb.iString == -1) {
  142. // no string
  143. psz = NULL;
  144. } else if (HIWORD(tb.iString)) {
  145. // it's a string pointer
  146. psz = (LPTSTR) tb.iString;
  147. } else {
  148. // it's an index into toolbar string array
  149. SendMessage(_hwndSubject, TB_GETSTRING, MAKELONG(MAXLEN, tb.iString), (LPARAM)pszBuf);
  150. psz = pszBuf;
  151. }
  152. if (psz)
  153. tb.iString = (INT_PTR)psz;
  154. else
  155. tb.iString = -1;
  156. if (tb.iBitmap == -1) {
  157. int id = GetDlgCtrlID(_hwndSubject);
  158. NMTBDISPINFO tbgdi = {0};
  159. tbgdi.hdr.hwndFrom = _hwndSubject;
  160. tbgdi.hdr.idFrom = id;
  161. tbgdi.hdr.code = TBN_GETDISPINFO;
  162. tbgdi.dwMask = TBNF_IMAGE;
  163. tbgdi.idCommand = tb.idCommand;
  164. tbgdi.iImage = 0;
  165. tbgdi.lParam = tb.dwData;
  166. SendMessage(GetParent(_hwndSubject), WM_NOTIFY, (WPARAM)id, (LPARAM)&tbgdi);
  167. if(tbgdi.dwMask & TBNF_DI_SETITEM)
  168. tb.iBitmap = tbgdi.iImage;
  169. }
  170. SendMessage(_hwndMB, TB_ADDBUTTONS, 1, (LPARAM)&tb);
  171. }
  172. }
  173. }
  174. }
  175. STDMETHODIMP CToolbarMenu::IsWindowOwner(HWND hwnd)
  176. {
  177. if ( hwnd == _hwndMB)
  178. return S_OK;
  179. else
  180. return S_FALSE;
  181. }
  182. void CToolbarMenu::_CancelMenu()
  183. {
  184. IMenuPopup* pmp;
  185. if (EVAL(SUCCEEDED(_pcmb->QueryInterface(IID_IMenuPopup, (LPVOID*)&pmp)))) {
  186. // tell menuband it's time to die
  187. pmp->OnSelect(MPOS_FULLCANCEL);
  188. pmp->Release();
  189. }
  190. }
  191. STDMETHODIMP CToolbarMenu::OnWinEvent(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* plres)
  192. {
  193. HRESULT hres = S_FALSE;
  194. ASSERT(plres);
  195. switch (uMsg) {
  196. case WM_COMMAND:
  197. PostMessage(GetParent(_hwndSubject), WM_COMMAND, wParam, (LPARAM)_hwndSubject);
  198. _CancelMenu();
  199. hres = S_OK;
  200. break;
  201. case WM_NOTIFY:
  202. {
  203. LPNMHDR pnmh = (LPNMHDR) lParam;
  204. switch (pnmh->code) {
  205. case TBN_DROPDOWN:
  206. _fTrackingSubMenu = TRUE;
  207. pnmh->hwndFrom = _hwndSubject;
  208. MapWindowPoints(_hwndMB, _hwndSubject, (LPPOINT) &((LPNMTOOLBAR)pnmh)->rcButton, 2);
  209. *plres = SendMessage(GetParent(_hwndSubject), WM_NOTIFY, wParam, (LPARAM)pnmh);
  210. _CancelMenu();
  211. hres = S_OK;
  212. _fTrackingSubMenu = FALSE;
  213. break;
  214. case NM_CUSTOMDRAW:
  215. // override mnbase custom draw shiznits
  216. *plres = 0;
  217. hres = S_OK;
  218. break;
  219. default:
  220. goto DoDefault;
  221. }
  222. break;
  223. }
  224. DoDefault:
  225. default:
  226. hres = SUPERCLASS::OnWinEvent(hwnd, uMsg, wParam, lParam, plres);
  227. }
  228. return hres;
  229. }
  230. CMenuToolbarBase* ToolbarMenu_Create(HWND hwnd)
  231. {
  232. return new CToolbarMenu(0, hwnd);
  233. }