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.

1976 lines
57 KiB

  1. /*
  2. * f m t b a r . c p p
  3. *
  4. * Format Bar based on IOleCommandTarget
  5. * Owner: brettm / a-mli
  6. *
  7. */
  8. #include <pch.hxx>
  9. #include "dllmain.h"
  10. #include <shfusion.h>
  11. #include "demand.h"
  12. #include "resource.h"
  13. #include "util.h"
  14. #include "mshtml.h"
  15. #include "mshtmhst.h"
  16. #include "mshtmcid.h"
  17. #include "docobj.h"
  18. #include "fmtbar.h"
  19. #include "strconst.h"
  20. #include "comctrlp.h"
  21. #include <shlguidp.h>
  22. /*
  23. * WS_EX_LAYOUTRTL ported from winuser.h
  24. */
  25. #if WINVER < 0X0500
  26. #define WS_EX_LAYOUTRTL 0x00400000L // Right to left mirroring
  27. #endif // WS_EX_LAYOUTRTL
  28. /*
  29. * m a c r o s
  30. */
  31. #define GETINDEX(m) ((DWORD)((((m & 0xff000000) >> 24) & 0x000000ff)))
  32. #define MAKEINDEX(b, l) (((DWORD)l & 0x00ffffff) | ((DWORD)b << 24))
  33. /*
  34. * c o n s t a n t s
  35. */
  36. #define cxButtonSep 8
  37. #define dxToolbarButton 16
  38. #define COMBOBUFSIZE 64
  39. #define dxFormatFontBitmap 20
  40. #define dyFormatFontBitmap 12
  41. #define NFONTSIZES 7
  42. #define TEMPBUFSIZE 30
  43. #define CYDROPDOWNEXPANDRATIO 8
  44. #define SIZETEXTLIMIT 8
  45. #define cxDUName 100
  46. #define cyToolbarOffset 2
  47. #define idcCoolbar 45
  48. // FormatBar stuff
  49. enum
  50. {
  51. itbFormattingTag,
  52. itbFormattingBold,
  53. itbFormattingItalic,
  54. itbFormattingUnderline,
  55. itbFormattingColor,
  56. itbFormattingNumbers,
  57. itbFormattingBullets,
  58. itbFormattingDecreaseIndent,
  59. itbFormattingIncreaseIndent,
  60. itbFormattingLeft,
  61. itbFormattingCenter,
  62. itbFormattingRight,
  63. itbFormattingJustify,
  64. itbFormattingInsertHLine,
  65. itbFormattingInsertLink,
  66. itbFormattingInsertImage,
  67. ctbFormatting
  68. };
  69. // FormatBar Paragraph direction stuff
  70. enum
  71. {
  72. itbFormattingBlockDirLTR = ctbFormatting,
  73. itbFormattingBlockDirRTL,
  74. };
  75. /*
  76. * t y p e d e f s
  77. */
  78. /*
  79. * g l o b a l d a t a
  80. */
  81. static const TCHAR c_szComboBox[] = "ComboBox",
  82. c_szFmtBarClass[] = "MimeEdit_FormatBar",
  83. c_szThis[] = "OE_This";
  84. /*
  85. * Color table for dropdown on toolbar. Matches COMMDLG colors
  86. * exactly.
  87. */
  88. static DWORD rgrgbColors[] =
  89. {
  90. RGB( 0, 0, 0), // "BLACK"},
  91. RGB(128, 0, 0), // "MAROON"},
  92. RGB( 0, 128, 0), // "GREEN"},
  93. RGB(128, 128, 0), // "OLIVE"},
  94. RGB( 0, 0, 128), // "NAVY"},
  95. RGB(128, 0, 128), // "PURPLE"},
  96. RGB( 0, 128, 128), // "TEAL"},
  97. RGB(128, 128, 128), // "GREY"},
  98. RGB(192, 192, 192), // "SILVER"},
  99. RGB(255, 0, 0), // "RED"},
  100. RGB( 0, 255, 0), // "LIME"},
  101. RGB(255, 255, 0), // "YELLOW"},
  102. RGB( 0, 0, 255), // "BLUE"},
  103. RGB(255, 0, 255), // "FUSCHIA"},
  104. RGB( 0, 255, 255), // "AQUA"},
  105. RGB(255, 255, 255) // "WHITE"}
  106. };
  107. static TBBUTTON rgtbbutton[] =
  108. {
  109. { itbFormattingTag, idmFmtTag,
  110. TBSTATE_ENABLED, TBSTYLE_DROPDOWN, {0}, 0L, -1 },
  111. { cxButtonSep, 0L,
  112. TBSTATE_ENABLED, TBSTYLE_SEP, {0}, 0L, -1 },
  113. { itbFormattingBold, idmFmtBold,
  114. TBSTATE_ENABLED, TBSTYLE_CHECK, {0}, 0L, -1 },
  115. { itbFormattingItalic, idmFmtItalic,
  116. TBSTATE_ENABLED, TBSTYLE_CHECK, {0}, 0L, -1 },
  117. { itbFormattingUnderline, idmFmtUnderline,
  118. TBSTATE_ENABLED, TBSTYLE_CHECK, {0}, 0L, -1 },
  119. { itbFormattingColor, idmFmtColor,
  120. TBSTATE_ENABLED, TBSTYLE_DROPDOWN, {0}, 0L, -1 },
  121. { cxButtonSep, 0L,
  122. TBSTATE_ENABLED, TBSTYLE_SEP, {0}, 0L, -1 },
  123. { itbFormattingNumbers, idmFmtNumbers,
  124. TBSTATE_ENABLED, TBSTYLE_CHECK, {0}, 0L, -1 },
  125. { itbFormattingBullets, idmFmtBullets,
  126. TBSTATE_ENABLED, TBSTYLE_CHECK, {0}, 0L, -1 },
  127. { itbFormattingDecreaseIndent, idmFmtDecreaseIndent,
  128. TBSTATE_ENABLED, TBSTYLE_BUTTON, {0}, 0L, -1 },
  129. { itbFormattingIncreaseIndent, idmFmtIncreaseIndent,
  130. TBSTATE_ENABLED, TBSTYLE_BUTTON, {0}, 0L, -1 },
  131. { cxButtonSep, 0L,
  132. TBSTATE_ENABLED, TBSTYLE_SEP, {0}, 0L, -1 },
  133. { itbFormattingLeft, idmFmtLeft,
  134. TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, {0}, 0L, -1 },
  135. { itbFormattingCenter, idmFmtCenter,
  136. TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, {0}, 0L, -1 },
  137. { itbFormattingRight, idmFmtRight,
  138. TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, {0}, 0L, -1 },
  139. { itbFormattingJustify, idmFmtJustify,
  140. TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, {0}, 0L, -1 },
  141. { cxButtonSep, 0L,
  142. TBSTATE_ENABLED, TBSTYLE_SEP, {0}, 0L, -1 },
  143. { itbFormattingInsertHLine, idmFmtInsertHLine,
  144. TBSTATE_ENABLED, TBSTYLE_BUTTON, {0}, 0L, -1 },
  145. { itbFormattingInsertLink, idmEditLink,
  146. TBSTATE_ENABLED, TBSTYLE_BUTTON, {0}, 0L, -1 },
  147. { itbFormattingInsertImage, idmInsertImage,
  148. TBSTATE_ENABLED, TBSTYLE_BUTTON, {0}, 0L, -1 }
  149. };
  150. static TBBUTTON rgtbblkdirbutton[] =
  151. {
  152. { itbFormattingBlockDirLTR, idmFmtBlockDirLTR,
  153. TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, {0}, 0L, -1 },
  154. { itbFormattingBlockDirRTL, idmFmtBlockDirRTL,
  155. TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, {0}, 0L, -1 },
  156. { cxButtonSep, 0L,
  157. TBSTATE_ENABLED, TBSTYLE_SEP, {0}, 0L, -1 }
  158. };
  159. #define ctbbutton (sizeof(rgtbbutton) / sizeof(TBBUTTON))
  160. /*
  161. * p r o t o t y p e s
  162. */
  163. HRESULT ColorMenu_Show(HMENU hmenuColor, HWND hwndParent, POINT pt, COLORREF *pclrf);
  164. void Color_WMDrawItem(HWND hwnd, LPDRAWITEMSTRUCT pdis);
  165. void Color_WMMeasureItem(HWND hwnd, HDC hdc, LPMEASUREITEMSTRUCT pmis);
  166. INT GetColorIndex(INT rbg);
  167. HFONT hFontGetMenuFont(HWND hwnd);
  168. /*
  169. * f u n c t i o n s
  170. */
  171. CFmtBar::CFmtBar(BOOL fSep)
  172. {
  173. m_cRef=1;
  174. m_hwnd = NULL;
  175. m_hwndToolbar = NULL;
  176. m_hwndName = NULL;
  177. m_hwndSize = NULL;
  178. m_wndprocEdit = NULL;
  179. m_wndprocNameComboBox = NULL;
  180. m_wndprocSizeComboBox = NULL;
  181. m_hbmName = NULL;
  182. m_hmenuColor = NULL;
  183. m_hmenuTag = NULL;
  184. m_fDestroyTagMenu = 1;
  185. m_pCmdTarget=0;
  186. m_fVisible = 0;
  187. m_fSep = !!fSep;
  188. m_himlHot = NULL;
  189. m_himl = NULL;
  190. }
  191. CFmtBar::~CFmtBar()
  192. {
  193. if (m_hbmName)
  194. DeleteObject(m_hbmName);
  195. if (m_hmenuColor)
  196. DestroyMenu(m_hmenuColor);
  197. if (m_hmenuTag && !!m_fDestroyTagMenu)
  198. DestroyMenu(m_hmenuTag);
  199. _FreeImageLists();
  200. }
  201. ULONG CFmtBar::AddRef()
  202. {
  203. return ++m_cRef;
  204. }
  205. ULONG CFmtBar::Release()
  206. {
  207. ULONG cRef=--m_cRef;
  208. if(m_cRef==0)
  209. delete this;
  210. return cRef;
  211. }
  212. HRESULT CreateColorMenu(ULONG idmStart, HMENU* pMenu)
  213. {
  214. DWORD irgb;
  215. DWORD mniColor;
  216. if(pMenu == NULL)
  217. return E_INVALIDARG;
  218. *pMenu = CreatePopupMenu();
  219. if (*pMenu == NULL)
  220. return E_OUTOFMEMORY;
  221. // Add the COLORREF version of each entry into the menu
  222. for (irgb = 0, mniColor=idmStart; irgb < sizeof(rgrgbColors)/sizeof(DWORD); ++irgb, ++mniColor)
  223. AppendMenu(*pMenu, MF_ENABLED|MF_OWNERDRAW, mniColor, (LPCSTR)IntToPtr(MAKEINDEX(irgb, rgrgbColors[irgb])));
  224. return S_OK;
  225. }
  226. LRESULT CALLBACK CFmtBar::ExtWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  227. {
  228. LPFORMATBAR pFmtBar=0;
  229. if (msg==WM_NCCREATE)
  230. {
  231. pFmtBar=(CFmtBar *)((LPCREATESTRUCT)lParam)->lpCreateParams;
  232. if(!pFmtBar)
  233. return -1;
  234. return (pFmtBar->OnNCCreate(hwnd)==S_OK);
  235. }
  236. pFmtBar = (LPFORMATBAR)GetWndThisPtr(hwnd);
  237. if (pFmtBar)
  238. return pFmtBar->WndProc(hwnd, msg, wParam, lParam);
  239. else
  240. return DefWindowProc(hwnd, msg, wParam, lParam);
  241. }
  242. extern BOOL g_fCanEditBiDi;
  243. HRESULT CFmtBar::OnNCCreate(HWND hwnd)
  244. {
  245. RECT rc;
  246. HFONT hfontOld,
  247. hfontToolbar;
  248. HWND hwndEdit,
  249. hwndToolTips;
  250. BOOL fRet;
  251. HDC hdc,
  252. hdcParent;
  253. TEXTMETRIC tm;
  254. INT yPos;
  255. INT cxDownButton;
  256. INT cxName;
  257. INT cxSize,
  258. cx;
  259. INT cyToolbarButton;
  260. INT cyDropDownRollHeight;
  261. INT cyExpandedList;
  262. const POINT pt = {5, 5};
  263. LONG lstyle;
  264. TOOLINFO ti;
  265. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this);
  266. m_hwnd=hwnd;
  267. AddRef();
  268. m_hwndRebar = CreateWindowEx(0, REBARCLASSNAME, NULL,
  269. WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN |
  270. WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NOPARENTALIGN,
  271. 0, 0, 100, 136, m_hwnd, (HMENU) idcCoolbar, g_hInst, NULL);
  272. if (!m_hwndRebar)
  273. return E_OUTOFMEMORY;
  274. SendMessage(m_hwndRebar, RB_SETTEXTCOLOR, 0, (LPARAM)GetSysColor(COLOR_BTNTEXT));
  275. SendMessage(m_hwndRebar, RB_SETBKCOLOR, 0, (LPARAM)GetSysColor(COLOR_BTNFACE));
  276. //SendMessage(m_hwndRebar, RB_SETEXTENDEDSTYLE, RBS_EX_OFFICE9, RBS_EX_OFFICE9);
  277. SendMessage(m_hwndRebar, CCM_SETVERSION, COMCTL32_VERSION, 0);
  278. // [a-msadek]; Fix for bug#55069
  279. // DO NOT remove CCS_TOP from creation styles below
  280. // It is a default style and toolbar WinProc will addit any way durin
  281. // WM_NCCREATE processing. However, it will cause WM_STYLECHANGING to be sent
  282. // Due to a bug in SetWindowPos() for a mirrored window, it will never return from seding
  283. // messages calling a stack overflow
  284. // No need to put it only for a mirrored window since it will be added any way
  285. // Look @ comctl32\toolbar.c, functions ToolbarWndProc() and TBAutoSize();
  286. m_hwndToolbar = CreateWindowEx(WS_EX_TOOLWINDOW, TOOLBARCLASSNAME, NULL,
  287. WS_CHILD|WS_CLIPCHILDREN|WS_VISIBLE|CCS_TOP|CCS_NOPARENTALIGN|CCS_NODIVIDER|
  288. TBSTYLE_TOOLTIPS|TBSTYLE_FLAT,
  289. 0, 0, 0, 0, m_hwndRebar, NULL,
  290. g_hInst, NULL);
  291. if (!m_hwndToolbar)
  292. return E_OUTOFMEMORY;
  293. SendMessage(m_hwndToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
  294. SendMessage(m_hwndToolbar, TB_ADDBUTTONS, (WPARAM)ctbbutton, (LPARAM)rgtbbutton);
  295. SendMessage(m_hwndToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(dxToolbarButton, dxToolbarButton));
  296. _SetToolbarBitmaps();
  297. // add BiDi direction buttons
  298. if(g_fCanEditBiDi)
  299. {
  300. SendMessage(m_hwndToolbar, TB_INSERTBUTTON, ctbbutton - 3, (LPARAM) (LPVOID) &rgtbblkdirbutton[2]);
  301. SendMessage(m_hwndToolbar, TB_INSERTBUTTON, ctbbutton - 3, (LPARAM) (LPVOID) &rgtbblkdirbutton[1]);
  302. SendMessage(m_hwndToolbar, TB_INSERTBUTTON, ctbbutton - 3, (LPARAM) (LPVOID) &rgtbblkdirbutton[0]);
  303. SendMessage(m_hwndToolbar, TB_AUTOSIZE, (WPARAM)0, (LPARAM)0);
  304. }
  305. hdcParent = GetDC(GetParent(hwnd));
  306. if (!hdcParent)
  307. return E_OUTOFMEMORY;
  308. hdc = CreateCompatibleDC(hdcParent);
  309. ReleaseDC(GetParent(hwnd), hdcParent);
  310. if (!hdc)
  311. return E_OUTOFMEMORY;
  312. hfontToolbar = (HFONT) SendMessage(m_hwndToolbar, WM_GETFONT, 0, 0);
  313. // Get font metrics (of System font) so that we can properly scale the
  314. // format bar layout
  315. hfontOld = (HFONT)SelectObject(hdc, hfontToolbar);
  316. GetTextMetrics(hdc, &tm);
  317. cxDownButton = GetSystemMetrics(SM_CXVSCROLL) + GetSystemMetrics(SM_CXDLGFRAME);
  318. cxName = (cxDUName * tm.tmAveCharWidth) / 4 + cxDownButton;
  319. cxSize = XFontSizeCombo(hdc) + cxDownButton;
  320. SelectObject(hdc, hfontOld);
  321. DeleteDC(hdc);
  322. // set the size of the formatbar based on the size of the toolbar plus 2 pixels padding
  323. GetClientRect(m_hwndToolbar, &rc);
  324. SetWindowPos(m_hwnd, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top + (2*cyToolbarOffset) + (m_fSep?2:0), SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE);
  325. // Determine how tall the buttons are so we can size our other controls
  326. // accordingly
  327. SendMessage(m_hwndToolbar, TB_GETITEMRECT, 1, (LPARAM) &rc);
  328. cyToolbarButton = rc.bottom - rc.top + 1;
  329. // Figure out size of expanded dropdown lists
  330. cyExpandedList = CYDROPDOWNEXPANDRATIO * cyToolbarButton;
  331. // Get the ToolTips window handle
  332. hwndToolTips = (HWND) SendMessage(m_hwndToolbar, TB_GETTOOLTIPS, 0, 0);
  333. m_hwndName = CreateWindow(c_szComboBox, NULL,
  334. WS_CHILD | WS_VSCROLL | CBS_DROPDOWN |
  335. CBS_SORT | CBS_HASSTRINGS |
  336. CBS_OWNERDRAWFIXED |WS_VISIBLE,
  337. 0, 0, cxName, cyExpandedList,
  338. m_hwndToolbar,
  339. (HMENU) idmFmtFont, g_hLocRes, NULL);
  340. if (!m_hwndName)
  341. return E_OUTOFMEMORY;
  342. ComboBox_SetExtendedUI(m_hwndName, TRUE);
  343. // Load up the mini-icons for TrueType or Printer font
  344. m_hbmName = LoadDIBBitmap(idbFormatBarFont);
  345. if (!m_hbmName)
  346. return E_OUTOFMEMORY;
  347. // Compute the right edge of the combobox
  348. SetWindowFont(m_hwndName, hfontToolbar, TRUE);
  349. // The Size
  350. m_hwndSize = CreateWindow(c_szComboBox, NULL,
  351. WS_CHILD | WS_VSCROLL | CBS_DROPDOWNLIST |
  352. WS_VISIBLE,
  353. cxName + cxButtonSep, 0, cxSize, cyExpandedList,
  354. m_hwndToolbar,
  355. (HMENU) idmFmtSize, g_hLocRes, NULL);
  356. if (!m_hwndSize)
  357. return E_OUTOFMEMORY;
  358. m_hwndTT = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL, 0,
  359. CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  360. NULL, (HMENU) NULL, g_hInst, NULL);
  361. if (!m_hwndTT)
  362. return E_OUTOFMEMORY;
  363. ZeroMemory(&ti, sizeof(TOOLINFO));
  364. ti.cbSize = sizeof(TOOLINFO);
  365. ti.uFlags = TTF_IDISHWND | TTF_TRANSPARENT | TTF_TRACK | TTF_ABSOLUTE;
  366. ti.hwnd = m_hwndName;
  367. ti.uId = (ULONG_PTR)m_hwndName;
  368. SendMessage(m_hwndTT, TTM_ADDTOOL, 0, (LPARAM)&ti);
  369. SendMessage(m_hwndTT, WM_SETFONT, (WPARAM)(HFONT)SendMessage(m_hwndToolbar, WM_GETFONT, 0, 0), 0);
  370. ComboBox_SetExtendedUI(m_hwndSize, TRUE);
  371. SetWindowFont(m_hwndSize, hfontToolbar, TRUE);
  372. // font sizes up to 4 digits are allowed
  373. ComboBox_LimitText(m_hwndSize, SIZETEXTLIMIT);
  374. // The color popup menu (initially empty)
  375. // Set the rolled-up heights of the combo boxes to all be the same
  376. cyDropDownRollHeight = LOWORD(SendMessage(m_hwndSize, CB_GETITEMHEIGHT, (WPARAM)-1, 0));
  377. // hwndName is ownerdrawn
  378. SendMessage(m_hwndName, CB_SETITEMHEIGHT, (WPARAM)-1, cyDropDownRollHeight);
  379. // Determine how tall the toolbar is so we can center the comboboxes
  380. GetClientRect(m_hwndToolbar, &rc);
  381. // Get size of toolbar window
  382. yPos = rc.bottom;
  383. // Get size of combobox
  384. GetClientRect(m_hwndSize, &rc);
  385. yPos = (yPos - rc.bottom) / 2;
  386. // We have a mirroring bug in GetWindowRect
  387. // It will give wrong cocordinates causing combos to go outside the screen
  388. // Ignore y-positioning in this case
  389. if(!(GetWindowLong(m_hwndToolbar, GWL_EXSTYLE) & WS_EX_LAYOUTRTL))
  390. {
  391. GetWindowRect(m_hwndName, &rc);
  392. MapWindowPoints(NULL, hwnd, (LPPOINT)&rc, 2);
  393. MoveWindow(m_hwndName, rc.left, yPos, rc.right-rc.left, rc.bottom-rc.top, FALSE);
  394. GetWindowRect(m_hwndSize, &rc);
  395. MapWindowPoints(NULL, hwnd, (LPPOINT)&rc, 2);
  396. MoveWindow(m_hwndSize, rc.left, yPos, rc.right-rc.left, rc.bottom-rc.top, FALSE);
  397. }
  398. hwndEdit = ::GetWindow(m_hwndName, GW_CHILD);
  399. // Add tooltips for the controls we just added
  400. AddToolTip(hwndToolTips, m_hwndName, idsTTFormattingFont);
  401. AddToolTip(hwndToolTips, m_hwndSize, idsTTFormattingSize);
  402. AddToolTip(hwndToolTips, hwndEdit, idsTTFormattingFont);
  403. // Subclass the comboboxes and their edit controls
  404. // Do the name edit control first
  405. m_wndprocEdit = SubclassWindow(hwndEdit, EditSubProc);
  406. m_wndprocNameComboBox = SubclassWindow(m_hwndName, ComboBoxSubProc);
  407. m_wndprocSizeComboBox = SubclassWindow(m_hwndSize, ComboBoxSubProc);
  408. // give the control This pointers
  409. SetProp(m_hwndName, c_szThis, (LPVOID)this);
  410. SetProp(m_hwndSize, c_szThis, (LPVOID)this);
  411. SetProp(hwndEdit, c_szThis, (LPVOID)this);
  412. GetClientRect(m_hwndToolbar, &rc);
  413. cx = cxName + cxSize + cxButtonSep * 2;
  414. REBARBANDINFO rbbi;
  415. POINT ptIdeal = {0};
  416. SendMessage(m_hwndToolbar, TB_GETIDEALSIZE, FALSE, (LPARAM)&ptIdeal);
  417. ZeroMemory(&rbbi, sizeof(rbbi));
  418. rbbi.cbSize = sizeof(REBARBANDINFO);
  419. rbbi.fMask = RBBIM_SIZE | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE | RBBIM_STYLE;
  420. rbbi.fStyle = RBBS_USECHEVRON;
  421. rbbi.cx = 0;
  422. rbbi.hwndChild = m_hwndToolbar;
  423. rbbi.cxMinChild = 0;
  424. rbbi.cyMinChild = rc.bottom;
  425. rbbi.cxIdeal = ptIdeal.x + cx;
  426. SendMessage(m_hwndRebar, RB_INSERTBAND, (UINT)-1, (LPARAM)(LPREBARBANDINFO)&rbbi);
  427. // Indent the toolbar buttons for the comboboxes
  428. SendMessage(m_hwndToolbar, TB_SETINDENT, cx, 0);
  429. // Load up the names of the fonts and colors
  430. FillFontNames();
  431. FillSizes();
  432. return S_OK;
  433. }
  434. void CFmtBar::OnNCDestroy()
  435. {
  436. SetWindowLongPtr(m_hwnd, GWLP_USERDATA, 0);
  437. m_hwnd=0;
  438. Release();
  439. }
  440. LRESULT CALLBACK CFmtBar::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  441. {
  442. switch(msg)
  443. {
  444. case WM_DESTROY:
  445. // unsubclass the windows
  446. if (m_wndprocEdit)
  447. {
  448. SubclassWindow(::GetWindow(m_hwndName, GW_CHILD), m_wndprocEdit);
  449. RemoveProp(::GetWindow(m_hwndName, GW_CHILD), c_szThis);
  450. }
  451. if (m_wndprocNameComboBox)
  452. {
  453. SubclassWindow(m_hwndName, m_wndprocNameComboBox);
  454. RemoveProp(m_hwndName, c_szThis);
  455. }
  456. if (m_wndprocSizeComboBox)
  457. {
  458. SubclassWindow(m_hwndSize, m_wndprocSizeComboBox);
  459. RemoveProp(m_hwndSize, c_szThis);
  460. }
  461. DestroyWindow(m_hwndTT);
  462. m_hwndTT=NULL;
  463. break;
  464. case WM_NCDESTROY:
  465. OnNCDestroy();
  466. break;
  467. case WM_COMMAND:
  468. if(OnWMCommand(GET_WM_COMMAND_HWND(wParam, lParam),
  469. GET_WM_COMMAND_ID(wParam, lParam),
  470. GET_WM_COMMAND_CMD(wParam, lParam))==S_OK)
  471. return 0;
  472. break;
  473. case WM_PAINT:
  474. if (m_fSep)
  475. {
  476. HDC hdc;
  477. PAINTSTRUCT ps;
  478. RECT rc;
  479. hdc=BeginPaint(hwnd, &ps);
  480. if (hdc)
  481. {
  482. GetClientRect(hwnd, &rc);
  483. rc.top = rc.bottom-3;
  484. //rc.bottom+=1;
  485. DrawEdge(hdc, &rc, BDR_RAISEDOUTER, BF_BOTTOM);
  486. EndPaint(hwnd, &ps);
  487. }
  488. return 0;
  489. }
  490. break;
  491. case WM_NOTIFY:
  492. WMNotify(wParam, (NMHDR*)lParam);
  493. return 0;
  494. case WM_SIZE:
  495. {
  496. RECT rc;
  497. GetClientRect(m_hwndRebar, &rc);
  498. // resize the width of the toolbar
  499. if(rc.right != (INT)LOWORD(lParam))
  500. SetWindowPos(m_hwndRebar, NULL, 0, cyToolbarOffset, LOWORD(lParam), HIWORD(lParam), SWP_NOZORDER|SWP_NOACTIVATE);
  501. }
  502. break;
  503. case WM_DRAWITEM:
  504. OnDrawItem((LPDRAWITEMSTRUCT)lParam);
  505. break;
  506. case WM_SYSCOLORCHANGE:
  507. _SetToolbarBitmaps();
  508. UpdateRebarBandColors(m_hwndRebar);
  509. // fall thro'
  510. case WM_WININICHANGE:
  511. case WM_DISPLAYCHANGE:
  512. case WM_QUERYNEWPALETTE:
  513. case WM_PALETTECHANGED:
  514. SendMessage(m_hwndRebar, msg, wParam, lParam);
  515. break;
  516. case WM_MEASUREITEM:
  517. OnMeasureItem((LPMEASUREITEMSTRUCT)lParam);
  518. break;
  519. }
  520. return DefWindowProc(hwnd, msg, wParam, lParam);
  521. }
  522. HRESULT CFmtBar::Init(HWND hwndParent, int idDlgItem)
  523. {
  524. // stuff these values. We don't create the formatbar until the first call to Show()
  525. // to allow better perf.
  526. m_hwndParent = hwndParent;
  527. m_idd = idDlgItem;
  528. return S_OK;
  529. }
  530. // displays the colorpopup menu at the specified point. if clrf if NULL, then no clrf is returned
  531. // but instead the appropriate WM_COMMAND is dispatched to the parent window
  532. HRESULT ColorMenu_Show(HMENU hmenuColor, HWND hwndParent, POINT pt, COLORREF *pclrf)
  533. {
  534. HRESULT hr=NOERROR;
  535. int tpm=TPM_LEFTALIGN|TPM_LEFTBUTTON;
  536. if(hmenuColor == NULL)
  537. return E_INVALIDARG;
  538. if(pclrf)
  539. tpm|=TPM_RETURNCMD;
  540. int id = TrackPopupMenu(hmenuColor, tpm,pt.x, pt.y, 0, hwndParent, NULL);
  541. switch(id)
  542. {
  543. case 1:
  544. return NOERROR;
  545. case 0:
  546. return E_FAIL;
  547. case -1:
  548. return MIMEEDIT_E_USERCANCEL;
  549. case idmFmtColor1:
  550. case idmFmtColor2:
  551. case idmFmtColor3:
  552. case idmFmtColor4:
  553. case idmFmtColor5:
  554. case idmFmtColor6:
  555. case idmFmtColor7:
  556. case idmFmtColor8:
  557. case idmFmtColor9:
  558. case idmFmtColor10:
  559. case idmFmtColor11:
  560. case idmFmtColor12:
  561. case idmFmtColor13:
  562. case idmFmtColor14:
  563. case idmFmtColor15:
  564. case idmFmtColor16:
  565. AssertSz(pclrf, "this HAS to be set to get this id back...");
  566. *pclrf=rgrgbColors[id-idmFmtColor1];
  567. return NOERROR;
  568. default:
  569. AssertSz(0, "unexpected return from TrackPopupMenu");
  570. }
  571. return E_FAIL;
  572. }
  573. HRESULT CFmtBar::CheckColor()
  574. {
  575. HRESULT hr=E_FAIL;
  576. INT iFound = -1, irgb;
  577. VARIANTARG va;
  578. if (!m_pCmdTarget)
  579. return E_FAIL;
  580. va.vt = VT_I4;
  581. va.lVal = -1;
  582. hr = m_pCmdTarget->Exec(&CMDSETID_Forms3,
  583. IDM_FORECOLOR,
  584. MSOCMDEXECOPT_DONTPROMPTUSER,
  585. NULL, &va);
  586. if(FAILED(hr))
  587. goto error;
  588. if(va.lVal == -1)
  589. goto error;
  590. iFound = GetColorIndex(va.lVal);
  591. error:
  592. CheckMenuRadioItem(m_hmenuColor, idmFmtColor1, idmFmtColor16, idmFmtColor1+iFound, MF_BYCOMMAND);
  593. return hr;
  594. }
  595. INT GetColorIndex(INT rbg)
  596. {
  597. INT iFound = -1;
  598. for (int irgb = 1; irgb < sizeof(rgrgbColors)/sizeof(DWORD); ++irgb)
  599. if ((rbg&0x00ffffff) == (LONG)rgrgbColors[irgb])
  600. {
  601. iFound = irgb;
  602. break;
  603. }
  604. return iFound;
  605. }
  606. HRESULT CFmtBar::HrInitTagMenu()
  607. {
  608. HRESULT hr=NOERROR;
  609. int id;
  610. int tpm=TPM_LEFTALIGN|TPM_LEFTBUTTON;
  611. VARIANTARG va;
  612. VARIANTARG *pvaIn=0;
  613. TCHAR szBufMenu[MAX_PATH] = {0};
  614. TCHAR szBufTag[MAX_PATH] = {0};
  615. if (!m_pCmdTarget)
  616. return E_FAIL;
  617. if (!m_hmenuTag &&
  618. FAILED(HrCreateTridentMenu(m_pCmdTarget, TM_TAGMENU, idmFmtTagFirst, idmFmtTagLast-idmFmtTagFirst, &m_hmenuTag)))
  619. return E_FAIL;
  620. hr = HrCheckTridentMenu(m_pCmdTarget, TM_TAGMENU, idmFmtTagFirst, idmFmtTagLast, m_hmenuTag);
  621. return hr;
  622. }
  623. HRESULT CFmtBar::HrShowTagMenu(POINT pt)
  624. {
  625. HRESULT hr;
  626. int tpm=TPM_LEFTALIGN|TPM_LEFTBUTTON;
  627. hr = HrInitTagMenu();
  628. if(FAILED(hr))
  629. return hr;
  630. TrackPopupMenu(m_hmenuTag, tpm, pt.x, pt.y, 0, m_hwnd, NULL);
  631. return hr;
  632. }
  633. HMENU CFmtBar::hmenuGetStyleTagMenu()
  634. {
  635. HRESULT hr;
  636. hr = HrInitTagMenu();
  637. if(FAILED(hr))
  638. return NULL;
  639. m_fDestroyTagMenu = 0;
  640. return m_hmenuTag;
  641. }
  642. // update toolbar buttons and font name/size combo boxes.
  643. HRESULT CFmtBar::Update()
  644. {
  645. UINT uCmdID=0;
  646. CHAR szBuf[COMBOBUFSIZE/2];
  647. CHAR szBufbstrVal[COMBOBUFSIZE/2];
  648. int i;
  649. INT iPointSize=0, iHTMLSize=0;
  650. HWND hwndEdit;
  651. OLECMD rgCmds[]= {
  652. {IDM_FONTNAME, 0},
  653. {IDM_FONTSIZE, 0},
  654. {IDM_FORECOLOR, 0},
  655. {IDM_BOLD, 0},
  656. {IDM_ITALIC, 0},
  657. {IDM_UNDERLINE, 0},
  658. {IDM_ORDERLIST, 0},
  659. {IDM_UNORDERLIST, 0},
  660. {IDM_JUSTIFYLEFT, 0},
  661. {IDM_JUSTIFYRIGHT, 0},
  662. {IDM_JUSTIFYCENTER, 0},
  663. {IDM_JUSTIFYFULL, 0},
  664. {IDM_BLOCKDIRLTR, 0},
  665. {IDM_BLOCKDIRRTL, 0},
  666. {IDM_OUTDENT, 0},
  667. {IDM_INDENT, 0},
  668. {IDM_HORIZONTALLINE, 0},
  669. {IDM_HYPERLINK, 0},
  670. {IDM_IMAGE, 0},
  671. {IDM_BLOCKFMT, 0}};
  672. int rgidm[] = { 0,
  673. 0,
  674. idmFmtColor,
  675. idmFmtBold,
  676. idmFmtItalic,
  677. idmFmtUnderline,
  678. idmFmtNumbers,
  679. idmFmtBullets,
  680. idmFmtLeft,
  681. idmFmtRight,
  682. idmFmtCenter,
  683. idmFmtJustify,
  684. idmFmtBlockDirLTR,
  685. idmFmtBlockDirRTL,
  686. idmFmtDecreaseIndent,
  687. idmFmtIncreaseIndent,
  688. idmFmtInsertHLine,
  689. idmEditLink,
  690. idmInsertImage,
  691. idmFmtTag};
  692. ULONG uState;
  693. BOOL fUIActive;
  694. if (!m_hwnd) // no UI visible yet
  695. return S_OK;
  696. if (!m_pCmdTarget)
  697. {
  698. EnableWindow(m_hwndName, FALSE);
  699. EnableWindow(m_hwndSize, FALSE);
  700. for (i=2; i<sizeof(rgCmds)/sizeof(OLECMD); i++)
  701. SendMessage(m_hwndToolbar, TB_SETSTATE, rgidm[i], MAKELONG(0, 0));
  702. return S_OK;
  703. }
  704. HWND hwndFocus = GetFocus();
  705. if (m_hwndToolbar == hwndFocus ||
  706. (hwndFocus && m_hwndToolbar==GetParent(hwndFocus)) ||
  707. (hwndFocus && GetParent(hwndFocus) && m_hwndToolbar==GetParent(GetParent(hwndFocus))) )
  708. return S_OK;
  709. fUIActive = FBodyHasFocus();
  710. if (fUIActive)
  711. m_pCmdTarget->QueryStatus(&CMDSETID_Forms3, sizeof(rgCmds)/sizeof(OLECMD), rgCmds, NULL);
  712. EnableWindow(m_hwndName, fUIActive && (rgCmds[0].cmdf&OLECMDF_ENABLED));
  713. EnableWindow(m_hwndSize, fUIActive && (rgCmds[1].cmdf&OLECMDF_ENABLED));
  714. for (i=2; i<sizeof(rgCmds)/sizeof(OLECMD); i++)
  715. {
  716. uState=(rgCmds[i].cmdf&OLECMDF_LATCHED ? TBSTATE_PRESSED: 0)|
  717. (rgCmds[i].cmdf&OLECMDF_ENABLED ? TBSTATE_ENABLED: 0);
  718. SendMessage(m_hwndToolbar, TB_SETSTATE, rgidm[i], MAKELONG(uState, 0));
  719. }
  720. if (!fUIActive)
  721. return S_OK;
  722. // update font name combo box
  723. VARIANTARG va;
  724. va.vt = VT_BSTR;
  725. va.bstrVal = NULL;
  726. if (m_pCmdTarget->Exec(&CMDSETID_Forms3, IDM_FONTNAME, MSOCMDEXECOPT_DONTPROMPTUSER, NULL, &va) == S_OK)
  727. {
  728. hwndEdit = ::GetWindow(m_hwndName, GW_CHILD);
  729. if (va.vt == VT_BSTR)
  730. {
  731. *szBuf = 0;
  732. *szBufbstrVal = 0;
  733. // we have a font-name, let's see if we need to update
  734. ComboBox_GetText(hwndEdit, szBuf, COMBOBUFSIZE/2);
  735. WideCharToMultiByte(CP_ACP, 0, (WCHAR*)va.bstrVal, -1, szBufbstrVal, COMBOBUFSIZE/2, NULL, NULL);
  736. if (StrCmpI(szBufbstrVal, szBuf) != 0)
  737. {
  738. if(ComboBox_SelectString(m_hwndName, -1, szBufbstrVal) == -1)
  739. ComboBox_SetText(hwndEdit, szBufbstrVal);
  740. }
  741. SafeSysFreeString(va.bstrVal);
  742. }
  743. else
  744. ComboBox_SetText(hwndEdit, "");
  745. }
  746. // update font size combo box
  747. va.vt = VT_I4;
  748. va.lVal = 0;
  749. if (m_pCmdTarget->Exec(&CMDSETID_Forms3, IDM_FONTSIZE, MSOCMDEXECOPT_DONTPROMPTUSER, NULL, &va)==S_OK &&
  750. va.vt == VT_I4)
  751. {
  752. // font size if returned in the 1 to 7 range, for I4
  753. // see if the font size has changed
  754. *szBuf = 0;
  755. if(ComboBox_GetText(m_hwndSize, szBuf, sizeof(szBuf)))
  756. {
  757. iPointSize = StrToInt(szBuf);
  758. Assert(iPointSize>=8 && iPointSize<=36);
  759. iHTMLSize = PointSizeToHTMLSize(iPointSize);
  760. }
  761. if(iHTMLSize != va.lVal)
  762. ComboBox_SetCurSel(m_hwndSize, va.lVal-1);
  763. }
  764. else
  765. ComboBox_SetCurSel(m_hwndSize, -1);
  766. return S_OK;
  767. }
  768. HRESULT CFmtBar::OnWMCommand(HWND hwnd, int id, WORD wCmd)
  769. {
  770. UINT uCmdID=0;
  771. VARIANTARG va;
  772. VARIANTARG *pvaIn=0;
  773. HRESULT hr = S_FALSE;
  774. DWORD dwOpt=MSOCMDEXECOPT_DONTPROMPTUSER;
  775. TOOLINFO ti;
  776. ZeroMemory(&va, sizeof(va));
  777. switch(wCmd)
  778. {
  779. case CBN_SELENDCANCEL:
  780. // clear the tooltip
  781. ZeroMemory(&ti, sizeof(TOOLINFO));
  782. ti.cbSize = sizeof(TOOLINFO);
  783. ti.hwnd = m_hwndName;
  784. ti.uId = (ULONG_PTR)m_hwndName;
  785. SendMessage(m_hwndTT, TTM_TRACKACTIVATE, FALSE, (LPARAM) &ti);
  786. break;
  787. case CBN_SELENDOK:
  788. {
  789. CHAR szBuf[COMBOBUFSIZE];
  790. UINT uSel;
  791. // clear the tooltip
  792. ZeroMemory(&ti, sizeof(TOOLINFO));
  793. ti.cbSize = sizeof(TOOLINFO);
  794. ti.hwnd = m_hwndName;
  795. ti.uId = (ULONG_PTR)m_hwndName;
  796. SendMessage(m_hwndTT, TTM_TRACKACTIVATE, FALSE, (LPARAM) &ti);
  797. if(idmFmtFont == id)
  798. {
  799. uCmdID = IDM_FONTNAME;
  800. uSel = ComboBox_GetCurSel(m_hwndName);
  801. // if(uSel < 0)
  802. // return hr;
  803. ComboBox_GetLBText(m_hwndName, uSel, szBuf);
  804. va.vt = VT_BSTR;
  805. pvaIn = &va;
  806. hr=HrLPSZToBSTR(szBuf, &va.bstrVal);
  807. if (FAILED(hr))
  808. goto Cleanup;
  809. }
  810. else if(idmFmtSize == id)
  811. {
  812. // when setting font size use:
  813. // VT_I4: for 1 - 7 range
  814. // VT_STRING: for -2 -> +4 range.
  815. uCmdID = IDM_FONTSIZE;
  816. uSel = ComboBox_GetCurSel(m_hwndSize);
  817. if(-1 == uSel)
  818. return hr;
  819. va.vt = VT_I4;
  820. va.lVal = uSel + 1;
  821. pvaIn = &va;
  822. }
  823. // set focus back to Trident, call HrUIActivate() after ComboBox operations.
  824. SetBodyFocus();
  825. hr = ExecCommand(uCmdID, dwOpt, pvaIn);
  826. if(FAILED(hr))
  827. goto Cleanup;
  828. Cleanup:
  829. if(va.vt == VT_BSTR && va.bstrVal != NULL)
  830. SysFreeString(va.bstrVal);
  831. return hr;
  832. }
  833. }
  834. switch(id)
  835. {
  836. case idmFmtBold:
  837. uCmdID=IDM_BOLD;
  838. break;
  839. case idmFmtItalic:
  840. uCmdID=IDM_ITALIC;
  841. break;
  842. case idmFmtUnderline:
  843. uCmdID=IDM_UNDERLINE;
  844. break;
  845. case idmAccelBullets:
  846. case idmFmtBullets:
  847. uCmdID=IDM_UNORDERLIST;
  848. break;
  849. case idmFmtNumbers:
  850. uCmdID=IDM_ORDERLIST;
  851. break;
  852. case idmAccelJustify:
  853. case idmFmtJustify:
  854. uCmdID=IDM_JUSTIFYFULL;
  855. break;
  856. case idmAccelLeft:
  857. case idmFmtLeft:
  858. uCmdID=IDM_JUSTIFYLEFT;
  859. break;
  860. case idmAccelCenter:
  861. case idmFmtCenter:
  862. uCmdID=IDM_JUSTIFYCENTER;
  863. break;
  864. case idmAccelRight:
  865. case idmFmtRight:
  866. uCmdID=IDM_JUSTIFYRIGHT;
  867. break;
  868. case idmFmtBlockDirLTR:
  869. uCmdID=IDM_BLOCKDIRLTR;
  870. break;
  871. case idmFmtBlockDirRTL:
  872. uCmdID=IDM_BLOCKDIRRTL;
  873. break;
  874. case idmAccelDecreaseIndent:
  875. case idmFmtDecreaseIndent:
  876. uCmdID=IDM_OUTDENT;
  877. break;
  878. case idmAccelIncreaseIndent:
  879. case idmFmtIncreaseIndent:
  880. uCmdID=IDM_INDENT;
  881. break;
  882. case idmEditLink:
  883. uCmdID=IDM_HYPERLINK;
  884. dwOpt = MSOCMDEXECOPT_PROMPTUSER;
  885. break;
  886. case idmUnInsertLink:
  887. uCmdID=IDM_UNLINK;
  888. break;
  889. case idmFmtInsertHLine:
  890. uCmdID=IDM_HORIZONTALLINE;
  891. break;
  892. case idmInsertImage:
  893. uCmdID=IDM_IMAGE;
  894. dwOpt = MSOCMDEXECOPT_PROMPTUSER;
  895. break;
  896. case idmFmtColor1:
  897. case idmFmtColor2:
  898. case idmFmtColor3:
  899. case idmFmtColor4:
  900. case idmFmtColor5:
  901. case idmFmtColor6:
  902. case idmFmtColor7:
  903. case idmFmtColor8:
  904. case idmFmtColor9:
  905. case idmFmtColor10:
  906. case idmFmtColor11:
  907. case idmFmtColor12:
  908. case idmFmtColor13:
  909. case idmFmtColor14:
  910. case idmFmtColor15:
  911. case idmFmtColor16:
  912. {
  913. uCmdID = IDM_FORECOLOR;
  914. va.vt = VT_I4;
  915. va.lVal = rgrgbColors[id-idmFmtColor1];
  916. pvaIn = &va;
  917. break;
  918. }
  919. }
  920. if(id >= idmFmtTagFirst && id <= idmFmtTagLast) //style tags
  921. {
  922. TCHAR szBuf[MAX_PATH] = {0};
  923. GetMenuString(m_hmenuTag, id, szBuf, MAX_PATH, MF_BYCOMMAND);
  924. Assert(*szBuf);//should not be empty
  925. hr=HrLPSZToBSTR(szBuf, &va.bstrVal);
  926. if (FAILED(hr))
  927. goto error;
  928. va.vt = VT_BSTR;
  929. pvaIn = &va;
  930. uCmdID = IDM_BLOCKFMT;
  931. }
  932. if(0 != uCmdID && m_pCmdTarget)
  933. {
  934. hr = ExecCommand(uCmdID, dwOpt, pvaIn);
  935. if(FAILED(hr))
  936. goto error;
  937. }
  938. error:
  939. if(va.vt == VT_BSTR && va.bstrVal != NULL)
  940. SysFreeString(va.bstrVal);
  941. return hr;
  942. }
  943. HRESULT CFmtBar::ExecCommand(UINT uCmdID, DWORD dwOpt, VARIANTARG *pvaIn)
  944. {
  945. HRESULT hr = S_FALSE;
  946. if(uCmdID && m_pCmdTarget)
  947. hr = m_pCmdTarget->Exec(&CMDSETID_Forms3,
  948. uCmdID,
  949. dwOpt,
  950. pvaIn, NULL);
  951. return hr;
  952. }
  953. HRESULT CFmtBar::SetCommandTarget(LPOLECOMMANDTARGET pCmdTarget)
  954. {
  955. // ALERT: we don't refcount these to avoid circular counts
  956. // as this poitner is valid during the lifetime of the formatbar
  957. m_pCmdTarget=pCmdTarget;
  958. return NOERROR;
  959. }
  960. HRESULT HrCreateFormatBar(HWND hwndParent, int iddlg, BOOL fSep, LPFORMATBAR *ppFmtBar)
  961. {
  962. LPFORMATBAR pFmtBar=0;
  963. HRESULT hr;
  964. if(!ppFmtBar)
  965. return E_INVALIDARG;
  966. *ppFmtBar=NULL;
  967. if(!(pFmtBar=new CFmtBar(fSep)))
  968. return E_OUTOFMEMORY;
  969. hr=pFmtBar->Init(hwndParent, iddlg);
  970. if(FAILED(hr))
  971. goto error;
  972. *ppFmtBar=pFmtBar;
  973. pFmtBar->AddRef();
  974. error:
  975. ReleaseObj(pFmtBar);
  976. return hr;
  977. }
  978. void CFmtBar::WMNotify(WPARAM wParam, NMHDR* pnmhdr)
  979. {
  980. LPNMREBARCHEVRON pnmch;
  981. if (pnmhdr->idFrom == idcCoolbar)
  982. {
  983. switch (pnmhdr->code)
  984. {
  985. case RBN_CHEVRONPUSHED:
  986. {
  987. ITrackShellMenu* ptsm;
  988. CoCreateInstance(CLSID_TrackShellMenu, NULL, CLSCTX_INPROC_SERVER, IID_ITrackShellMenu,
  989. (LPVOID*)&ptsm);
  990. if (!ptsm)
  991. break;
  992. ptsm->Initialize(0, 0, 0, SMINIT_TOPLEVEL|SMINIT_VERTICAL);
  993. LPNMREBARCHEVRON pnmch = (LPNMREBARCHEVRON) pnmhdr;
  994. ptsm->SetObscured(m_hwndToolbar, NULL, SMSET_TOP);
  995. MapWindowPoints(m_hwndRebar, HWND_DESKTOP, (LPPOINT)&pnmch->rc, 2);
  996. POINTL pt = {pnmch->rc.left, pnmch->rc.right};
  997. ptsm->Popup(m_hwndRebar, &pt, (RECTL*)&pnmch->rc, MPPF_BOTTOM);
  998. ptsm->Release();
  999. break;
  1000. }
  1001. }
  1002. }
  1003. switch(pnmhdr->code)
  1004. {
  1005. case TBN_DROPDOWN:
  1006. {
  1007. RECT rc;
  1008. POINT pt;
  1009. LPTBNOTIFY pTBN = (LPTBNOTIFY) pnmhdr;
  1010. if(pTBN->iItem == idmFmtColor)
  1011. SendMessage(m_hwndToolbar, TB_GETITEMRECT, 5, (LPARAM) &rc);
  1012. else if(pTBN->iItem == idmFmtTag)
  1013. SendMessage(m_hwndToolbar, TB_GETITEMRECT, 1, (LPARAM) &rc);
  1014. MapWindowPoints(m_hwndToolbar, NULL, (LPPOINT)&rc, 2);
  1015. pt.x=(GetWindowLong(m_hwndToolbar, GWL_EXSTYLE) & WS_EX_LAYOUTRTL) ?rc.right : rc.left;
  1016. pt.y=rc.bottom+2;
  1017. if(pTBN->iItem == idmFmtColor)
  1018. {
  1019. CheckColor();
  1020. ColorMenu_Show(m_hmenuColor, m_hwnd, pt, NULL);
  1021. }
  1022. else
  1023. if(pTBN->iItem == idmFmtTag)
  1024. HrShowTagMenu(pt);
  1025. }
  1026. break;
  1027. case TTN_NEEDTEXT:
  1028. ProcessTooltips((LPTOOLTIPTEXTOE) pnmhdr);
  1029. break;
  1030. }
  1031. }
  1032. void CFmtBar::OnDrawItem(LPDRAWITEMSTRUCT pdis)
  1033. {
  1034. switch(pdis->CtlType)
  1035. {
  1036. case ODT_MENU:
  1037. Color_WMDrawItem(m_hwnd, pdis);
  1038. break;
  1039. case ODT_COMBOBOX:
  1040. ComboBox_WMDrawItem(pdis);
  1041. break;
  1042. default:
  1043. AssertSz(0, "OwnerDraw type not supported");
  1044. }
  1045. }
  1046. void CFmtBar::OnMeasureItem(LPMEASUREITEMSTRUCT pmis)
  1047. {
  1048. HDC hdc;
  1049. HFONT hfontOld;
  1050. TEXTMETRIC tm;
  1051. hdc = GetDC(m_hwnd);
  1052. if(hdc)
  1053. {
  1054. switch(pmis->CtlType)
  1055. {
  1056. case ODT_MENU:
  1057. Color_WMMeasureItem(m_hwnd, hdc, pmis);
  1058. break;
  1059. case ODT_COMBOBOX:
  1060. hfontOld = (HFONT)SelectObject(hdc, (HFONT)SendMessage(m_hwndToolbar, WM_GETFONT, 0, 0));
  1061. GetTextMetrics(hdc, &tm);
  1062. SelectObject(hdc, hfontOld);
  1063. pmis->itemHeight = tm.tmHeight;
  1064. break;
  1065. default:
  1066. AssertSz(0, "OwnerDraw type not supported");
  1067. }
  1068. ReleaseDC(m_hwnd, hdc);
  1069. }
  1070. }
  1071. void Color_WMMeasureItem(HWND hwnd, HDC hdc, LPMEASUREITEMSTRUCT pmis)
  1072. {
  1073. HFONT hfontOld;
  1074. TEXTMETRIC tm;
  1075. UINT id = pmis->itemID;
  1076. TCHAR szColor[MAX_PATH]={0};
  1077. Assert (pmis->CtlType == ODT_MENU);
  1078. hfontOld = (HFONT)SelectObject(hdc, hFontGetMenuFont(hwnd));
  1079. GetTextMetrics(hdc, &tm);
  1080. SelectObject(hdc, hfontOld);
  1081. ULONG index = GETINDEX(pmis->itemData);
  1082. LoadString(g_hLocRes, index + idsColor1,
  1083. szColor, sizeof(szColor)/sizeof(TCHAR));
  1084. pmis->itemHeight = tm.tmHeight;
  1085. pmis->itemWidth = GetSystemMetrics(SM_CXMENUCHECK) +
  1086. 2 * GetSystemMetrics(SM_CXBORDER) +
  1087. 2 * tm.tmHeight +
  1088. (lstrlen(szColor) + 2) *tm.tmAveCharWidth;
  1089. }
  1090. // fill font name combo box
  1091. void CFmtBar::FillFontNames()
  1092. {
  1093. LOGFONT lf = {0};
  1094. HDC hdc;
  1095. // reset the contents of the combo
  1096. SendMessage(m_hwndName, CB_RESETCONTENT, 0, 0);
  1097. hdc = GetDC(NULL);
  1098. if (hdc)
  1099. {
  1100. //to enumerate all styles of all fonts for the default character set
  1101. lf.lfFaceName[0] = '\0';
  1102. lf.lfCharSet = DEFAULT_CHARSET;
  1103. EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC)ExtEnumFontNamesProcEx, (LPARAM)this, 0);
  1104. ReleaseDC(NULL, hdc);
  1105. }
  1106. }
  1107. LRESULT CALLBACK CFmtBar::EditSubProc(HWND hwnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
  1108. {
  1109. CHAR szBuf[TEMPBUFSIZE];
  1110. HWND hwndCombo = GetParent(hwnd);
  1111. LPFORMATBAR pFmtBar = NULL;
  1112. if(hwndCombo == NULL)
  1113. {
  1114. AssertSz(0, "This is bad");
  1115. return 0;
  1116. }
  1117. pFmtBar = (LPFORMATBAR)GetProp(hwnd, c_szThis);
  1118. if(pFmtBar == NULL)
  1119. {
  1120. AssertSz(0, "This is bad");
  1121. return 0;
  1122. }
  1123. *szBuf = 0;
  1124. switch (wMsg)
  1125. {
  1126. case WM_KEYDOWN:
  1127. switch(wParam)
  1128. {
  1129. case VK_ESCAPE:
  1130. pFmtBar->SetBodyFocus();
  1131. return 0;
  1132. case VK_RETURN:
  1133. if (!SendMessage(pFmtBar->m_hwndName, CB_GETDROPPEDSTATE, 0, 0))
  1134. {
  1135. ComboBox_GetText(hwnd, szBuf, sizeof(szBuf));
  1136. ComboBox_SelectString(pFmtBar->m_hwndName, -1, szBuf);
  1137. SendMessage(pFmtBar->m_hwnd, WM_COMMAND, (WPARAM)MAKELONG(idmFmtFont, CBN_SELENDOK), (LPARAM)pFmtBar->m_hwndName);
  1138. return 0;
  1139. }
  1140. }
  1141. break;
  1142. case WM_LBUTTONDOWN:
  1143. case WM_LBUTTONUP:
  1144. case WM_MOUSEMOVE:
  1145. {
  1146. MSG msg;
  1147. msg.lParam = lParam;
  1148. msg.wParam = wParam;
  1149. msg.message = wMsg;
  1150. msg.hwnd = hwnd;
  1151. SendMessage((HWND)SendMessage(pFmtBar->m_hwndToolbar, TB_GETTOOLTIPS, 0, 0), TTM_RELAYEVENT, 0, (LPARAM) &msg);
  1152. }
  1153. break;
  1154. }
  1155. return CallWindowProc(pFmtBar->m_wndprocEdit, hwnd, wMsg, wParam, lParam);
  1156. }
  1157. LRESULT CALLBACK CFmtBar::ComboBoxSubProc(HWND hwnd, UINT wMsg, WPARAM wParam,
  1158. LPARAM lParam)
  1159. {
  1160. INT nID = GetWindowID(hwnd);
  1161. WNDPROC wndprocNext;
  1162. LPFORMATBAR pFmtBar = NULL;
  1163. pFmtBar = (LPFORMATBAR)GetProp(hwnd, c_szThis);
  1164. if(pFmtBar == NULL)
  1165. {
  1166. AssertSz(0, "This is bad");
  1167. return 0;
  1168. }
  1169. switch (wMsg)
  1170. {
  1171. case WM_LBUTTONDOWN:
  1172. case WM_LBUTTONUP:
  1173. case WM_MOUSEMOVE:
  1174. {
  1175. MSG msg;
  1176. msg.lParam = lParam;
  1177. msg.wParam = wParam;
  1178. msg.message = wMsg;
  1179. msg.hwnd = hwnd;
  1180. SendMessage((HWND)SendMessage(pFmtBar->m_hwndToolbar, TB_GETTOOLTIPS, 0, 0), TTM_RELAYEVENT, 0, (LPARAM) &msg);
  1181. }
  1182. break;
  1183. }
  1184. if (nID == idmFmtFont)
  1185. wndprocNext = pFmtBar->m_wndprocNameComboBox;
  1186. else
  1187. wndprocNext = pFmtBar->m_wndprocSizeComboBox;
  1188. return wndprocNext ? CallWindowProc(wndprocNext, hwnd, wMsg, wParam, lParam) : 0;
  1189. }
  1190. INT CALLBACK CFmtBar::ExtEnumFontNamesProcEx(ENUMLOGFONTEX *plf, NEWTEXTMETRICEX *ptm, INT nFontType, LPARAM lParam)
  1191. {
  1192. return ((CFmtBar *)lParam)->EnumFontNamesProcEx(plf, ptm, nFontType);
  1193. }
  1194. INT CFmtBar::EnumFontNamesProcEx(ENUMLOGFONTEX *plf, NEWTEXTMETRICEX *ptm, INT nFontType)
  1195. {
  1196. CFmtBar *pFmtBar;
  1197. LONG l;
  1198. // skip vertical fonts for OE
  1199. if (plf->elfLogFont.lfFaceName[0]=='@')
  1200. return TRUE;
  1201. // if the font is already listed, don't re-list it
  1202. if(ComboBox_FindStringExact(m_hwndName, -1, plf->elfLogFont.lfFaceName) != -1)
  1203. return TRUE;
  1204. l = ComboBox_AddString(m_hwndName, plf->elfLogFont.lfFaceName);
  1205. if (l!=-1)
  1206. ComboBox_SetItemData(m_hwndName, l, nFontType);
  1207. return TRUE;
  1208. }
  1209. INT CFmtBar::XFontSizeCombo(HDC hdc)
  1210. {
  1211. LONG id;
  1212. TCHAR szBuf[TEMPBUFSIZE];
  1213. *szBuf = 0;
  1214. INT iMax=0;
  1215. SIZE rSize;
  1216. for(id = idsFontSize0; id < NFONTSIZES + idsFontSize0; ++id)
  1217. {
  1218. LoadString(g_hLocRes, id, szBuf, sizeof(szBuf));
  1219. GetTextExtentPoint32 (hdc, szBuf, lstrlen(szBuf), &rSize);
  1220. if(rSize.cx > iMax)
  1221. iMax = rSize.cx;
  1222. }
  1223. return iMax + 10;
  1224. }
  1225. void CFmtBar::FillSizes()
  1226. {
  1227. LONG id;
  1228. TCHAR szBuf[TEMPBUFSIZE];
  1229. *szBuf = 0;
  1230. LRESULT lr;
  1231. // Empty the current list
  1232. SendMessage(m_hwndSize, CB_RESETCONTENT, 0, 0);
  1233. for (id = idsFontSize0; id < NFONTSIZES + idsFontSize0; ++id)
  1234. {
  1235. LoadString(g_hLocRes, id, szBuf, sizeof(szBuf));
  1236. lr = SendMessage(m_hwndSize, CB_ADDSTRING, 0, (LPARAM) szBuf);
  1237. if (lr == CB_ERR || lr == CB_ERRSPACE)
  1238. break;
  1239. }
  1240. }
  1241. #define BACKGROUND 0x000000FF // bright blue
  1242. #define BACKGROUNDSEL 0x00FF00FF // bright blue
  1243. DWORD CFmtBar::FlipColor(DWORD rgb)
  1244. {
  1245. return RGB(GetBValue(rgb), GetGValue(rgb), GetRValue(rgb));
  1246. }
  1247. // load bitmap for true type font
  1248. HBITMAP CFmtBar::LoadDIBBitmap(int id)
  1249. {
  1250. HDC hdc;
  1251. HRSRC h;
  1252. DWORD FAR * p;
  1253. LPSTR lpBits;
  1254. HANDLE hRes;
  1255. LPBITMAPINFOHEADER lpBitmapInfo;
  1256. LPVOID lpRes;
  1257. DWORD cbRes;
  1258. int numcolors;
  1259. DWORD rgbSelected;
  1260. DWORD rgbUnselected;
  1261. HBITMAP hbm;
  1262. rgbSelected = FlipColor(GetSysColor(COLOR_HIGHLIGHT));
  1263. rgbUnselected = FlipColor(GetSysColor(COLOR_WINDOW));
  1264. h = FindResource(g_hLocRes, MAKEINTRESOURCE(id), RT_BITMAP);
  1265. hRes = LoadResource(g_hLocRes, h);
  1266. /* Lock the bitmap and get a pointer to the color table. */
  1267. lpRes = LockResource(hRes);
  1268. if (!lpRes)
  1269. return NULL;
  1270. /* Copy the resource since we shouldn't modify the original */
  1271. cbRes = SizeofResource(g_hLocRes, h);
  1272. if(!MemAlloc((LPVOID *)&lpBitmapInfo, LOWORD(cbRes)))
  1273. return NULL;
  1274. CopyMemory(lpBitmapInfo, lpRes, cbRes);
  1275. p = (DWORD FAR *)((LPSTR)(lpBitmapInfo) + lpBitmapInfo->biSize);
  1276. /* Search for the Solid Blue entry and replace it with the current
  1277. * background RGB.
  1278. */
  1279. numcolors = 16;
  1280. while (numcolors-- > 0)
  1281. {
  1282. if (*p == BACKGROUND)
  1283. *p = rgbUnselected;
  1284. else if (*p == BACKGROUNDSEL)
  1285. *p = rgbSelected;
  1286. p++;
  1287. }
  1288. /* First skip over the header structure */
  1289. lpBits = (LPSTR)(lpBitmapInfo + 1);
  1290. /* Skip the color table entries, if any */
  1291. lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
  1292. /* Create a color bitmap compatible with the display device */
  1293. hdc = GetDC(NULL);
  1294. hbm = CreateDIBitmap(hdc, lpBitmapInfo, (DWORD)CBM_INIT, lpBits,
  1295. (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS);
  1296. ReleaseDC(NULL, hdc);
  1297. SafeMemFree(lpBitmapInfo);
  1298. FreeResource(hRes);
  1299. return hbm;
  1300. }
  1301. VOID CFmtBar::AddToolTip(HWND hwndToolTips, HWND hwnd, UINT idRsrc)
  1302. {
  1303. TOOLINFO ti = { 0 };
  1304. ti.cbSize = sizeof(TOOLINFO);
  1305. ti.uFlags = TTF_IDISHWND;
  1306. ti.hwnd = hwnd;
  1307. ti.uId = (UINT_PTR) hwnd;
  1308. GetWindowRect(hwnd, &ti.rect);
  1309. ti.hinst = g_hLocRes;
  1310. ti.lpszText = (LPSTR) IntToPtr(idRsrc);
  1311. SendMessage(hwndToolTips, TTM_ADDTOOL, 0, (LPARAM) &ti);
  1312. }
  1313. HRESULT CFmtBar::TranslateAcclerator(LPMSG lpMsg)
  1314. {
  1315. HWND hwndFocus;
  1316. if (m_hwnd &&
  1317. lpMsg->message==WM_KEYDOWN &&
  1318. ((lpMsg->wParam==VK_RETURN || lpMsg->wParam==VK_ESCAPE)))
  1319. {
  1320. hwndFocus=GetFocus();
  1321. // if focus is on the size combolist or in the edit of the
  1322. // name combobox, then we translate the messages to the window.
  1323. if(hwndFocus==::GetWindow(m_hwndName, GW_CHILD) ||
  1324. hwndFocus==m_hwndSize)
  1325. {
  1326. TranslateMessage(lpMsg);
  1327. DispatchMessage(lpMsg);
  1328. return S_OK;
  1329. }
  1330. }
  1331. return S_FALSE;
  1332. }
  1333. BOOL CFmtBar::FBodyHasFocus()
  1334. {
  1335. NMHDR nmhdr;
  1336. nmhdr.hwndFrom=m_hwnd;
  1337. nmhdr.idFrom=GetDlgCtrlID(m_hwnd);
  1338. nmhdr.code=FBN_BODYHASFOCUS;
  1339. return (0 != SendMessage(GetParent(m_hwnd), WM_NOTIFY, nmhdr.idFrom, (LPARAM)&nmhdr));
  1340. }
  1341. void CFmtBar::SetBodyFocus()
  1342. {
  1343. NMHDR nmhdr;
  1344. nmhdr.hwndFrom=m_hwnd;
  1345. nmhdr.idFrom=GetDlgCtrlID(m_hwnd);
  1346. nmhdr.code=FBN_BODYSETFOCUS;
  1347. SendMessage(GetParent(m_hwnd), WM_NOTIFY, nmhdr.idFrom, (LPARAM)&nmhdr);
  1348. }
  1349. void CFmtBar::ComboBox_WMDrawItem(LPDRAWITEMSTRUCT pdis)
  1350. {
  1351. HDC hdc,
  1352. hdcMem;
  1353. DWORD rgbBack, rgbText;
  1354. char szFace[LF_FACESIZE + 10];
  1355. HBITMAP hbmOld;
  1356. int dy,
  1357. x;
  1358. INT nFontType = (INT) pdis->itemData;
  1359. SIZE size;
  1360. TOOLINFO ti;
  1361. RECT rc;
  1362. Assert(pdis->CtlID == idmFmtFont);
  1363. hdc = pdis->hDC;
  1364. if (pdis->itemState & ODS_SELECTED)
  1365. {
  1366. rgbBack = SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
  1367. rgbText = SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
  1368. }
  1369. else
  1370. {
  1371. rgbBack = SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
  1372. rgbText = SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
  1373. }
  1374. SendMessage(pdis->hwndItem, CB_GETLBTEXT, pdis->itemID,
  1375. (LPARAM)(LPSTR)szFace);
  1376. ExtTextOut(hdc, pdis->rcItem.left + dxFormatFontBitmap,
  1377. pdis->rcItem.top, ETO_OPAQUE, &pdis->rcItem,
  1378. szFace, lstrlen(szFace), NULL);
  1379. // if selected, see if it is clipped, so that we know to show a tooltip
  1380. if ((pdis->itemState & ODS_SELECTED) &&
  1381. GetTextExtentPoint32(hdc, szFace, lstrlen(szFace), &size) &&
  1382. size.cx + dxFormatFontBitmap >= pdis->rcItem.right)
  1383. {
  1384. ZeroMemory(&ti, sizeof(TOOLINFO));
  1385. ti.cbSize = sizeof(TOOLINFO);
  1386. ti.hwnd = m_hwndName;
  1387. ti.uId = (UINT_PTR)m_hwndName;
  1388. ti.lpszText = szFace;
  1389. SendMessage(m_hwndName, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)&rc);
  1390. SendMessage(m_hwndTT, TTM_UPDATETIPTEXT, 0, (LPARAM)&ti);
  1391. SendMessage(m_hwndTT, TTM_TRACKPOSITION, 0, MAKELPARAM(rc.left + pdis->rcItem.left + dxFormatFontBitmap,
  1392. rc.top + pdis->rcItem.top));
  1393. SendMessage(m_hwndTT, TTM_TRACKACTIVATE, TRUE, (LPARAM) &ti);
  1394. }
  1395. else
  1396. SendMessage(m_hwndTT, TTM_TRACKACTIVATE, FALSE, (LPARAM) &ti);
  1397. hdcMem = CreateCompatibleDC(hdc);
  1398. if (hdcMem)
  1399. {
  1400. if (m_hbmName)
  1401. {
  1402. hbmOld = (HBITMAP)SelectObject(hdcMem, m_hbmName);
  1403. x = dxFormatFontBitmap;
  1404. if (nFontType & TRUETYPE_FONTTYPE)
  1405. x = 0;
  1406. else if ((nFontType & (PRINTER_FONTTYPE | DEVICE_FONTTYPE)) ==
  1407. (PRINTER_FONTTYPE | DEVICE_FONTTYPE))
  1408. x = dxFormatFontBitmap;
  1409. else
  1410. goto SkipBlt;
  1411. dy = ((pdis->rcItem.bottom - pdis->rcItem.top) -
  1412. dyFormatFontBitmap) / 2;
  1413. BitBlt(hdc, pdis->rcItem.left, pdis->rcItem.top + dy,
  1414. dxFormatFontBitmap, dyFormatFontBitmap, hdcMem,
  1415. x, pdis->itemState & ODS_SELECTED ? dyFormatFontBitmap: 0,
  1416. SRCCOPY);
  1417. SkipBlt:
  1418. SelectObject(hdcMem, hbmOld);
  1419. }
  1420. DeleteDC(hdcMem);
  1421. }
  1422. SetTextColor(hdc, rgbText);
  1423. SetBkColor(hdc, rgbBack);
  1424. }
  1425. void Color_WMDrawItem(HWND hwnd, LPDRAWITEMSTRUCT pdis)
  1426. {
  1427. HBRUSH hbr;
  1428. WORD dx, dy, dxBorder;
  1429. RECT rc;
  1430. TCHAR szColor[MAX_PATH]={0};
  1431. DWORD rgbBack, rgbText;
  1432. UINT id = pdis->itemID;
  1433. ULONG index = 0;
  1434. Assert (pdis->CtlType == ODT_MENU);
  1435. if(pdis->itemState&ODS_SELECTED)
  1436. {
  1437. rgbBack = SetBkColor(pdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
  1438. rgbText = SetTextColor(pdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
  1439. }
  1440. else
  1441. {
  1442. rgbBack = SetBkColor(pdis->hDC, GetSysColor(COLOR_MENU));
  1443. rgbText = SetTextColor(pdis->hDC, GetSysColor(COLOR_MENUTEXT));
  1444. }
  1445. // compute coordinates of color rectangle and draw it
  1446. dxBorder = (WORD) GetSystemMetrics(SM_CXBORDER);
  1447. dx = (WORD) GetSystemMetrics(SM_CXMENUCHECK);
  1448. dy = (WORD) GetSystemMetrics(SM_CYBORDER);
  1449. rc.top = pdis->rcItem.top + dy;
  1450. rc.bottom = pdis->rcItem.bottom - dy;
  1451. rc.left = pdis->rcItem.left + dx;
  1452. rc.right = rc.left + 2 * (rc.bottom - rc.top);
  1453. index = GETINDEX(pdis->itemData);
  1454. LoadString(g_hLocRes, index + idsColor1,
  1455. szColor, sizeof(szColor)/sizeof(TCHAR));
  1456. SelectObject(pdis->hDC, hFontGetMenuFont(hwnd));
  1457. ExtTextOut(pdis->hDC, rc.right + 2*dxBorder,
  1458. pdis->rcItem.top, ETO_OPAQUE, &pdis->rcItem,
  1459. szColor, lstrlen(szColor), NULL);
  1460. hbr = CreateSolidBrush((DWORD)(pdis->itemData & 0x00ffffff));
  1461. if (hbr)
  1462. {
  1463. hbr = (HBRUSH)SelectObject (pdis->hDC, hbr);
  1464. Rectangle(pdis->hDC, rc.left, rc.top, rc.right, rc.bottom);
  1465. DeleteObject(SelectObject(pdis->hDC, hbr));
  1466. }
  1467. // draw radio check.
  1468. if (pdis->itemState&ODS_CHECKED)
  1469. {
  1470. WORD left, top, radius;
  1471. if(pdis->itemState&ODS_SELECTED)
  1472. hbr = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHTTEXT));
  1473. else
  1474. hbr = CreateSolidBrush(GetSysColor(COLOR_MENUTEXT));
  1475. if (hbr)
  1476. {
  1477. hbr = (HBRUSH)SelectObject (pdis->hDC, hbr);
  1478. #ifndef WIN16
  1479. left = (WORD) (pdis->rcItem.left + GetSystemMetrics(SM_CXMENUCHECK) / 2);
  1480. #else
  1481. left = pdis->rcItem.left + LOWORD( GetMenuCheckMarkDimensions() ) / 2;
  1482. #endif
  1483. top = (WORD) (rc.top + (rc.bottom - rc.top) / 2);
  1484. #ifndef WIN16
  1485. radius = (WORD) (GetSystemMetrics(SM_CXMENUCHECK) / 4);
  1486. #else
  1487. radius = LOWORD( GetMenuCheckMarkDimensions() ) / 4;
  1488. #endif
  1489. Ellipse(pdis->hDC, left-radius, top-radius, left+radius, top+radius);
  1490. DeleteObject(SelectObject(pdis->hDC, hbr));
  1491. }
  1492. }
  1493. SetTextColor(pdis->hDC, rgbText);
  1494. SetBkColor(pdis->hDC, rgbBack);
  1495. }
  1496. HRESULT CFmtBar::Show()
  1497. {
  1498. HRESULT hr;
  1499. if (m_fVisible)
  1500. return S_OK;
  1501. hr = AttachWin();
  1502. if (FAILED(hr))
  1503. return hr;
  1504. ShowWindow(m_hwnd, SW_SHOW);
  1505. m_fVisible=1;
  1506. Update();
  1507. return S_OK;
  1508. }
  1509. HRESULT CFmtBar::Hide()
  1510. {
  1511. if (!m_fVisible)
  1512. return S_OK;
  1513. ShowWindow(m_hwnd, SW_HIDE);
  1514. m_fVisible=0;
  1515. return S_OK;
  1516. }
  1517. HRESULT CFmtBar::GetWindow(HWND *pHwnd)
  1518. {
  1519. *pHwnd = m_hwnd;
  1520. return S_OK;
  1521. }
  1522. HRESULT CFmtBar::AttachWin()
  1523. {
  1524. HWND hwnd;
  1525. WNDCLASS wc;
  1526. if (m_hwnd) // already created
  1527. return S_OK;
  1528. if (FAILED(CreateColorMenu(idmFmtColor1, &m_hmenuColor)))
  1529. return E_FAIL;
  1530. if (!GetClassInfo(g_hLocRes, c_szFmtBarClass, &wc))
  1531. {
  1532. ZeroMemory(&wc, sizeof(WNDCLASS));
  1533. wc.style = CS_BYTEALIGNWINDOW;
  1534. wc.lpfnWndProc = CFmtBar::ExtWndProc;
  1535. wc.hInstance = g_hLocRes;
  1536. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  1537. wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
  1538. wc.lpszClassName = c_szFmtBarClass;
  1539. if (!RegisterClass(&wc))
  1540. return E_FAIL;
  1541. }
  1542. hwnd = CreateWindowEx(WS_EX_CONTROLPARENT,
  1543. c_szFmtBarClass, NULL,
  1544. WS_CHILD|WS_CLIPCHILDREN,
  1545. 0, 0, 0, 0,
  1546. m_hwndParent, (HMENU)IntToPtr(m_idd), g_hLocRes, (LPVOID)this);
  1547. if(!hwnd)
  1548. return E_OUTOFMEMORY;
  1549. return S_OK;
  1550. }
  1551. HFONT hFontGetMenuFont(HWND hwnd)
  1552. {
  1553. NMHDR nmhdr;
  1554. nmhdr.hwndFrom=hwnd;
  1555. nmhdr.idFrom=GetDlgCtrlID(hwnd);
  1556. nmhdr.code=FBN_GETMENUFONT;
  1557. return (HFONT)SendMessage(GetParent(hwnd), WM_NOTIFY, nmhdr.idFrom, (LPARAM)&nmhdr);
  1558. }
  1559. HRESULT CFmtBar::_SetToolbarBitmaps()
  1560. {
  1561. // release toolbar references
  1562. SendMessage(m_hwndToolbar, TB_SETIMAGELIST, 0, (LPARAM)NULL);
  1563. SendMessage(m_hwndToolbar, TB_SETHOTIMAGELIST, 0, (LPARAM)NULL);
  1564. _FreeImageLists();
  1565. // set the normal imagelist
  1566. m_himl = LoadMappedToolbarBitmap(g_hLocRes, idbFormatBar, dxToolbarButton);
  1567. if (!m_himl)
  1568. return E_OUTOFMEMORY;
  1569. SendMessage(m_hwndToolbar, TB_SETIMAGELIST, 0, (LPARAM)m_himl);
  1570. // the the HOT imagelist
  1571. m_himlHot = LoadMappedToolbarBitmap(g_hLocRes, idbFormatBarHot, dxToolbarButton);
  1572. if (!m_himlHot)
  1573. return E_OUTOFMEMORY;
  1574. SendMessage(m_hwndToolbar, TB_SETHOTIMAGELIST, 0, (LPARAM)m_himlHot);
  1575. return S_OK;
  1576. }
  1577. HRESULT CFmtBar::_FreeImageLists()
  1578. {
  1579. if (m_himlHot)
  1580. {
  1581. ImageList_Destroy(m_himlHot);
  1582. m_himlHot = NULL;
  1583. }
  1584. if (m_himl)
  1585. {
  1586. ImageList_Destroy(m_himl);
  1587. m_himl = NULL;
  1588. }
  1589. return S_OK;
  1590. }