home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / dbmsg / mapi / manager.sh / smhtb.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-11  |  23.8 KB  |  740 lines

  1. /*
  2.  *  S M H T B . C
  3.  *
  4.  *  Sample mail handling hook configuration toolbar
  5.  *  Copyright 1992-95 Microsoft Corporation.  All Rights Reserved.
  6.  */
  7.  
  8. #include "_pch.h"
  9. #include <richedit.h>
  10.  
  11. #ifndef WIN16
  12. #include <commctrl.h>
  13. #endif
  14.  
  15. /*  Maximum number of font digits */
  16.  
  17. #define cchSizeMax  16
  18.  
  19. /*  Enumeration of button bitmaps if toolbar bitmap */
  20.  
  21. enum {
  22.     itbBold,
  23.     itbItalic,
  24.     itbUnderline,
  25.     itbColor,
  26.     ctbMax
  27. };
  28.  
  29. /*  Gap sizes for format bar */
  30.  
  31. #define cxDownButton    16
  32. #define cxName          (125 + cxDownButton)
  33. #define cxSize          (40 + cxDownButton)
  34. #define cxPlaceHolder   (cxName + 8 + cxSize + 8)
  35. #define cxIndent        (1440 / 4)
  36.  
  37. /*  Button descriptions for format bar */
  38.  
  39. static const TBBUTTON rgtbbChar[] =
  40. {
  41.     { cxPlaceHolder, 0L, TBSTATE_ENABLED, TBSTYLE_SEP, {0}, 0L, -1},
  42.     { itbColor, ID_Color, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0}, 0L, -1 },
  43.     { itbBold, ID_Bold, TBSTATE_ENABLED, TBSTYLE_CHECK, {0}, 0L, -1},
  44.     { itbItalic, ID_Italic, TBSTATE_ENABLED, TBSTYLE_CHECK, {0}, 0L, -1},
  45.     { itbUnderline, ID_Underline, TBSTATE_ENABLED, TBSTYLE_CHECK, {0}, 0L, -1},
  46. };
  47. #define ctbbChar   (sizeof(rgtbbChar) / sizeof(TBBUTTON))
  48.  
  49. /*  Color descriptions for dropdown color list */
  50.  
  51. DWORD rgrgb[] = {
  52.     RGB(  0,   0,   0), /* Auto         */
  53.     RGB(  0,   0,   0), /* Black        */
  54.     RGB(128,   0,   0), /* Dark red     */
  55.     RGB(  0, 128,   0), /* Dark green   */
  56.     RGB(128, 128,   0), /* Dark yellow  */
  57.     RGB(  0,   0, 128), /* Dark blue    */
  58.     RGB(128,   0, 128), /* Dark purple  */
  59.     RGB(  0, 128, 128), /* Dark aqua    */
  60.     RGB(128, 128, 128), /* Dark grey    */
  61.     RGB(192, 192, 192), /* Light grey   */
  62.     RGB(255,   0,   0), /* Light red    */
  63.     RGB(  0, 255,   0), /* Light green  */
  64.     RGB(255, 255,   0), /* Light yellow */
  65.     RGB(  0,   0, 255), /* Light blue   */
  66.     RGB(255,   0, 255), /* Light purple */
  67.     RGB(  0, 255, 255), /* Light aqua   */
  68.     RGB(255, 255, 255), /* White        */
  69. };
  70. #define crgb    (sizeof(rgrgb) / sizeof(rgrgb[0]))
  71. const LPTSTR rgszColor[] = {
  72.     "Auto", "Black", "Maroon",
  73.     "Green", "Olive", "Navy",
  74.     "Purple", "Teal", "Gray",
  75.     "Silver", "Red", "Lime",
  76.     "Yellow", "Blue", "Fuchia",
  77.     "Aqua", "White"
  78. };
  79.  
  80. /*  Font and paragraph effects */
  81.     
  82. static const DWORD rgdwEffect[] = { CFE_BOLD, CFE_ITALIC, CFE_UNDERLINE };
  83. static const WORD rgwAlign[] = { PFA_LEFT, PFA_CENTER, PFA_RIGHT };
  84. static const UINT rglFontSize[] =
  85. {
  86.      8,  9, 10, 11,
  87.     12, 14, 16, 18,
  88.     20, 22, 24, 26,
  89.     28, 36, 48, 72
  90. };
  91. #define FontSize(_y)    MulDiv((int)(_y), 72, 1440)
  92.  
  93. /*  Toolbar and combobox class names */
  94.  
  95. static const TCHAR rgchTBClass[] = "SMHToolbar";
  96. static const TCHAR rgchComboBox[] = "ComboBox";
  97.  
  98. #ifdef  WIN16
  99. #define GWL_USERDATA 0
  100. #endif
  101.  
  102.  
  103. /*
  104.  *  Font, font size, and color dropdown and listing functions -----------------
  105.  *
  106.  *  These functions are used to fill in and display the character formats
  107.  *  for the format bar.  The font listbox gets filled once and only once
  108.  *  on format bar creation.  The font size listbox will get filled up each
  109.  *  and everytime the font list gets dropped down.  The font color menu
  110.  *  will get filled once at startup.
  111.  */
  112.  
  113. INT CALLBACK EXPORT
  114. EnumFontNames (LPVOID lpvLogFont,
  115.     NEWTEXTMETRIC FAR * lpntm,
  116.     INT nFontType,
  117.     LPARAM lParam)
  118. {
  119.     UINT i;
  120.     DWORD dw = 0;
  121.     LOGFONT FAR * lplf = FWin4Shell()
  122.                             ? &((ENUMLOGFONTEX FAR *)lpvLogFont)->elfLogFont
  123.                             : (LOGFONT FAR *)lpvLogFont;
  124.  
  125.     /*  Add the face name into the listbox */
  126.  
  127.     DebugTrace ("SMH: adding font: %s%s\n", lplf->lfFaceName,
  128.         (lpntm->tmPitchAndFamily & TMPF_TRUETYPE)
  129.             ? " (TrueType)"
  130.             : "");
  131.  
  132.     i = ComboBox_AddString ((HWND)lParam, lplf->lfFaceName);
  133.     if ((i != CB_ERR) || (i != CB_ERRSPACE))
  134.     {
  135.         Assert (!(lplf->lfCharSet & 0xFFFFFF00));
  136.         Assert (!(lplf->lfPitchAndFamily & 0xFFFFFF00));
  137.         Assert (!(nFontType & 0xFFFF0000));
  138.         dw = lplf->lfCharSet & 0xFF;
  139.         dw <<= 8;
  140.         dw |= lplf->lfPitchAndFamily & 0xFF;
  141.         dw <<= 16;
  142.         dw |= nFontType & 0xFFFF;
  143.         ComboBox_SetItemData ((HWND)lParam, i, dw);
  144.     }
  145.     return TRUE;
  146. }
  147.  
  148. void
  149. FillFontNames (HWND hwnd)
  150. {
  151.     HDC hdc;
  152.  
  153.     /*  Empty the contents of the listbox and enumerate the fonts */
  154.     
  155.     ComboBox_ResetContent (hwnd);
  156.     if (hdc = GetDC(NULL))
  157.     {
  158.         EnumFontFamilies (hdc,
  159.             (LPTSTR)NULL,
  160.             (FONTENUMPROC)EnumFontNames,
  161.             (LPARAM)(LPVOID)hwnd);
  162.         ReleaseDC (NULL, hdc);
  163.     }
  164. }
  165.  
  166. INT CALLBACK EXPORT
  167. EnumFontSizes (LPVOID lpvLogFont,
  168.     NEWTEXTMETRIC FAR * lpntm,
  169.     INT nFontType,
  170.     LPARAM lParam)
  171. {
  172.     TCHAR rgch[cchSizeMax];
  173.     UINT i;
  174.  
  175.     if (lpntm->tmPitchAndFamily & TMPF_TRUETYPE)
  176.     {
  177.         /*  If the font is TrueType, then just fillin random sizes */
  178.         
  179.         for (i = 0; i < (sizeof(rglFontSize) / sizeof(UINT)); i++)
  180.         {
  181.             wsprintf (rgch, "%d", rglFontSize[i]);
  182.             DebugTrace ("SMH: adding font size: %s\n", rgch);
  183.             ComboBox_AddString (((LPFORMATBAR)lParam)->hwndSize, rgch);
  184.         }
  185.         return FALSE;
  186.     }
  187.     else
  188.     {
  189.         /*  Calculate the size of the current instance */
  190.  
  191.         wsprintf (rgch, "%d", MulDiv ((INT)lpntm->tmHeight - lpntm->tmInternalLeading, 72,
  192.             GetDeviceCaps (((LPFORMATBAR)lParam)->hdc, LOGPIXELSY)));
  193.         if (ComboBox_FindStringExact (((LPFORMATBAR)lParam)->hwndSize, -1, rgch) == CB_ERR)
  194.         {
  195.             DebugTrace ("SMH: font height: %d\n", lpntm->tmHeight - lpntm->tmInternalLeading);
  196.             DebugTrace ("SMH: adding font size: %s\n", rgch);
  197.             ComboBox_AddString (((LPFORMATBAR)lParam)->hwndSize, rgch);
  198.             ((LPFORMATBAR)lParam)->cSize++;
  199.         }
  200.         return TRUE;
  201.     }
  202. }
  203.  
  204. void
  205. FillSizes (LPFORMATBAR lpfb)
  206. {
  207.     TCHAR rgch[30];
  208.  
  209.     /*  Empty the contents of the listbox and enumerate the fonts */
  210.     
  211.     ComboBox_ResetContent (lpfb->hwndSize);
  212.     ComboBox_GetText (lpfb->hwndFont, rgch, sizeof(rgch) - 1);
  213.  
  214.     if (lpfb->hdc = GetDC (lpfb->hwndSize))
  215.     {
  216.         lpfb->cSize = 0;
  217.         EnumFontFamilies (lpfb->hdc, rgch, (FONTENUMPROC)EnumFontSizes, (LPARAM)lpfb);
  218.         ReleaseDC (lpfb->hwndSize, lpfb->hdc);
  219.     }
  220. }
  221.  
  222. void CALLBACK
  223. ColorMenu_MeasureItem (HWND hwnd, MEASUREITEMSTRUCT FAR * lpmis)
  224. {
  225.     LPFORMATBAR lpfb = (LPFORMATBAR)GetWindowLong (hwnd, GWL_USERDATA);
  226.     HFONT hfnt;
  227.     TEXTMETRIC tm;
  228.  
  229.     hfnt = SelectObject (lpfb->hdc, lpfb->hfnt);
  230.     GetTextMetrics (lpfb->hdc, &tm);
  231.     SelectObject (lpfb->hdc, hfnt);
  232.     lpmis->itemHeight = tm.tmHeight;
  233.     lpmis->itemWidth = 14 * tm.tmAveCharWidth;
  234.     return;
  235. }
  236.  
  237. void CALLBACK EXPORT
  238. ColorMenu_DrawItem (HWND hwnd, DRAWITEMSTRUCT FAR * lpdis)
  239. {
  240.     LPFORMATBAR lpfb = (LPFORMATBAR)(GetWindowLong (hwnd, GWL_USERDATA));
  241.     HBRUSH hbr;
  242.     WORD dx;
  243.     WORD dy;
  244.     RECT rc;
  245.     DWORD rgbBack;
  246.     DWORD rgbText;
  247.  
  248.     if (lpdis->itemState & ODS_SELECTED)
  249.     {
  250.         rgbBack = SetBkColor (lpdis->hDC, GetSysColor (COLOR_HIGHLIGHT));
  251.         rgbText = SetTextColor (lpdis->hDC, GetSysColor (COLOR_HIGHLIGHTTEXT));
  252.     }
  253.     else
  254.     {
  255.         rgbBack = SetBkColor (lpdis->hDC, GetSysColor(COLOR_WINDOW));
  256.         rgbText = SetTextColor (lpdis->hDC, GetSysColor(COLOR_WINDOWTEXT));
  257.     }
  258.  
  259.     ExtTextOut (lpdis->hDC,
  260.             lpdis->rcItem.left,
  261.             lpdis->rcItem.top,
  262.             ETO_OPAQUE,
  263.             &lpdis->rcItem,
  264.             NULL, 0, NULL);
  265.  
  266.     dx = GetSystemMetrics(SM_CXBORDER);
  267.     dy = GetSystemMetrics(SM_CYBORDER);
  268.     rc.top = lpdis->rcItem.top + dy;
  269.     rc.bottom = lpdis->rcItem.bottom - dy;
  270.     rc.left = lpdis->rcItem.left + dx;
  271.     rc.right = rc.left + 2 * (rc.bottom - rc.top);
  272.  
  273.     if (hbr = CreateSolidBrush (lpdis->itemData))
  274.     {
  275.         hbr = SelectObject (lpdis->hDC, hbr);
  276.         Rectangle (lpdis->hDC, rc.left, rc.top, rc.right, rc.bottom);
  277.         DeleteObject (SelectObject (lpdis->hDC, hbr));
  278.     }
  279.  
  280.     DebugTrace ("SMH: color menu: painting item: %s\n",
  281.         (LPCSTR)rgszColor[lpdis->itemID - ID_Color - 1]);
  282.     SelectObject (lpdis->hDC, lpfb->hfnt);
  283.     TextOut (lpdis->hDC,
  284.         2 * dx + rc.right,
  285.         lpdis->rcItem.top,
  286.         rgszColor[lpdis->itemID - ID_Color - 1],
  287.         lstrlen ((LPCSTR)rgszColor[lpdis->itemID - ID_Color - 1]));
  288.  
  289.     SetTextColor (lpdis->hDC, rgbText);
  290.     SetBkColor (lpdis->hDC, rgbBack);
  291.     return;
  292. }
  293.  
  294. void
  295. FillColors (LPFORMATBAR lpfb)
  296. {
  297.     UINT irgb;
  298.  
  299.     /*  Setup the auto color */
  300.  
  301.     rgrgb[0] = GetSysColor (COLOR_WINDOWTEXT);
  302.  
  303.     for (irgb = 0; irgb < crgb; irgb++)
  304.     {
  305.         DebugTrace ("SMH: color menu: adding item: %s (0x%08lX)\n",
  306.             (LPCSTR)rgszColor[irgb], rgrgb[irgb]);
  307.         AppendMenu (lpfb->hmnuColor,
  308.             MF_ENABLED | MF_OWNERDRAW,
  309.             ID_Color + irgb + 1,
  310.             (LPCSTR)rgrgb[irgb]);
  311.     }
  312. }
  313.  
  314. /*
  315.  *  FormatBar window proc -----------------------------------------------------
  316.  *
  317.  *  The formatbar window proc intercepts several window messages and
  318.  *  processes them as needed.  The primary messages we operate on are the
  319.  *  messages that will cause items to be redrawn or shown.
  320.  *
  321.  *  Additionally, WM_DESTROY is processed as for cleanup of all the
  322.  *  formatbar components
  323.  */
  324.  
  325. LRESULT CALLBACK EXPORT
  326. FormatBarWndProc (HWND hwnd,
  327.     UINT msg,
  328.     WPARAM wParam,
  329.     LPARAM lParam)
  330. {
  331.     LPFORMATBAR lpfb = (LPFORMATBAR)GetWindowLong (hwnd, GWL_USERDATA);
  332.  
  333.     switch (msg)
  334.     {
  335.       case WM_COMMAND:
  336.         
  337.         if ((GET_WM_COMMAND_CMD (wParam, lParam) == CBN_DROPDOWN) &&
  338.             (GET_WM_COMMAND_ID (wParam, lParam) == ID_FontSize))
  339.             FillSizes (lpfb);
  340.         SendMessage (GetParent(hwnd), WM_COMMAND, wParam, lParam);
  341.         return TRUE;
  342.  
  343.       case WM_SHOWWINDOW:
  344.         
  345.         SendMessage (lpfb->hwndTb, msg, wParam, lParam);
  346.         break;
  347.  
  348.       case WM_DRAWITEM:
  349.         
  350.         ColorMenu_DrawItem (hwnd, (DRAWITEMSTRUCT FAR *)lParam);
  351.         return TRUE;
  352.  
  353.       case WM_MEASUREITEM:
  354.         
  355.         ColorMenu_MeasureItem (hwnd, (MEASUREITEMSTRUCT FAR *)lParam);
  356.         return TRUE;
  357.  
  358.       case WM_DESTROY:
  359.         
  360.         DebugTrace ("SMH: destroying format bar\n");
  361.         DestroyWindow (lpfb->hwndTb);
  362.         DestroyWindow (lpfb->hwndFont);
  363.         DestroyWindow (lpfb->hwndSize);
  364.         DeleteObject (lpfb->hbrBtnFace);
  365.         DestroyMenu (lpfb->hmnuColor);
  366.         UlRelease (lpfb->lpreoc);
  367.         (*lpfb->lpscd->lpfnFree) (lpfb);
  368.         break;
  369.     }
  370.     return DefWindowProc (hwnd, msg, wParam, lParam);
  371. }
  372.  
  373. /*
  374.  *  Toolbar subclass proc -----------------------------------------------------
  375.  *
  376.  *  The subclassing of the toolbar is done so that the listboxes added to
  377.  *  the toolbar will be drawn with the correct control color.
  378.  */
  379.  
  380. LRESULT CALLBACK EXPORT
  381. ToolbarSubclassProc (HWND hwnd,
  382.     UINT msg,
  383.     WPARAM wParam,
  384.     LPARAM lParam)
  385. {
  386.     LPFORMATBAR lpfb = (LPFORMATBAR)GetWindowLong (GetParent (hwnd), GWL_USERDATA);
  387.  
  388.     switch (msg)
  389.     {
  390. #ifdef _WIN32
  391.       case WM_CTLCOLORLISTBOX:
  392. #else
  393.       case WM_CTLCOLOR:
  394.   
  395.         switch (HIWORD (lParam))
  396.         {
  397.           case CTLCOLOR_LISTBOX:
  398. #endif
  399.             if (!lpfb->hbrBtnFace)
  400.             {
  401.                 lpfb->hbrBtnFace = CreateSolidBrush (FWin4Shell()
  402.                                                         ? GetSysColor (COLOR_WINDOW)
  403.                                                         : GetSysColor (COLOR_BTNFACE));
  404.             }
  405.             return (LRESULT)(LPVOID)lpfb->hbrBtnFace;
  406. #ifdef _WIN32
  407.             break;
  408. #else
  409.             break;
  410.         }
  411.         break;
  412. #endif
  413.     }
  414.  
  415.     return CallWindowProc (lpfb->lpfnToolbar, hwnd, msg, wParam, lParam);
  416. }
  417.  
  418. STDMETHODIMP_(SCODE)
  419. ScCreateToolbar (LPSCD lpscd,
  420.     HWND hwnd,
  421.     UINT idPeg,
  422.     BOOL fPropsheet,
  423.     LPFORMATBAR FAR * lppfb)
  424. {
  425.     SCODE sc;
  426.     RECT rc;
  427.     RECT rcId;
  428.     RECT rcTb;
  429.     RECT rcCli;
  430.     UINT x;
  431.     UINT y;
  432.     WNDCLASS wc = {0};
  433.     LPFORMATBAR lpfb = NULL;
  434.  
  435.     sc = (*lpscd->lpfnAlloc) (sizeof(FORMATBAR), &lpfb);
  436.     if (!FAILED (sc))
  437.     {
  438.         memset (lpfb, 0, sizeof(FORMATBAR));
  439.         lpfb->hwndEdit = GetDlgItem (hwnd, idPeg);
  440.  
  441.         lpfb->cf.cbSize = sizeof(CHARFORMAT);
  442.         SendMessage (lpfb->hwndEdit, EM_GETCHARFORMAT, TRUE, (LPARAM)(LPVOID)&lpfb->cf);
  443.         lpfb->pf.cbSize = sizeof(PARAFORMAT);
  444.         SendMessage (lpfb->hwndEdit, EM_GETPARAFORMAT, 0, (LPARAM)(LPVOID)&lpfb->pf);
  445.         SendMessage (lpfb->hwndEdit, EM_SETEVENTMASK, 0, ENM_SELCHANGE | ENM_CHANGE);
  446.  
  447.         lpfb->cf.dwMask = CFM_FACE | CFM_SIZE | CFE_BOLD | CFE_ITALIC | CFE_UNDERLINE | CFM_COLOR;
  448.         lpfb->cf.dwEffects = CFE_AUTOCOLOR;
  449.         lstrcpy (lpfb->cf.szFaceName, "Arial");
  450.         lpfb->cf.yHeight = 200;
  451.         SendMessage (lpfb->hwndEdit, EM_SETCHARFORMAT, 0, (LPARAM)(LPVOID)&lpfb->cf);
  452.  
  453.         if (!GetClassInfo (lpscd->hinst, rgchTBClass, &wc))
  454.         {
  455.             wc.style = CS_HREDRAW | CS_VREDRAW;
  456.             wc.lpfnWndProc = FormatBarWndProc;
  457.             wc.cbWndExtra = sizeof(LPVOID);
  458.             wc.hInstance = lpscd->hinst;
  459.             wc.hCursor = LoadCursor (NULL, IDC_ARROW);
  460.             wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  461.             wc.lpszClassName = (LPCTSTR)rgchTBClass;
  462.             SideAssert (RegisterClass (&wc));
  463.         }
  464.         Assert (IsWindow (hwnd));
  465.         GetWindowRect (lpfb->hwndEdit, &rcId);
  466.         if (lpfb->hwndFrame = CreateWindow ((LPCTSTR)rgchTBClass,
  467.                                         "SMH",
  468.                                         WS_CHILD,
  469.                                         0, 0, rcId.right, 30,
  470.                                         hwnd,
  471.                                         (HMENU)ID_Frame,
  472.                                         lpscd->hinst,
  473.                                         NULL))
  474.         {
  475.  
  476.             CTL3D_SubclassCtl (lpCtl3D, lpfb->hwndFrame);
  477.  
  478.             lpfb->hmnuColor = CreatePopupMenu();
  479.             FillColors (lpfb);
  480.  
  481.             if (lpfb->hwndTb = CreateToolbarEx (lpfb->hwndFrame,
  482.                                         CCS_TOP | WS_CHILD,
  483.                                         0,
  484.                                         ctbMax,
  485.                                         lpscd->hinst,
  486.                                         ID_Toolbar,
  487.                                         rgtbbChar,
  488.                                         ctbbChar,
  489.                                         16, 16, 16, 16,
  490.                                         sizeof(TBBUTTON)))
  491.             {
  492.                 lpfb->lpscd = lpscd;
  493.                 SetWindowLong (lpfb->hwndFrame, GWL_USERDATA, (ULONG)lpfb);
  494.  
  495.                 /*  Move the window to where it belongs */
  496.  
  497.                 GetWindowRect (hwnd, &rc);
  498.                 GetClientRect (lpfb->hwndTb, &rcTb);
  499.  
  500.                 x = rcId.left - rc.left;
  501.                 y = rcId.top - rc.top - rcTb.bottom - 2;
  502.  
  503.                 /*  Adjust y by any title bars and framing */
  504.  
  505.                 if (!fPropsheet)
  506.                 {
  507.                     GetClientRect (hwnd, &rcCli);
  508.                     y -= rc.bottom - rc.top - rcCli.bottom;
  509.                     x -= (rc.right - rc.left - rcCli.right) / 2;
  510.                     y += (rc.right - rc.left - rcCli.right) / 2;
  511.                 }
  512.  
  513.                 MoveWindow (lpfb->hwndFrame, x, y, rcId.right - rcId.left, rcTb.bottom, FALSE);
  514.  
  515.                 lpfb->hfnt = (HFONT) SendMessage (lpfb->hwndTb, WM_GETFONT, 0, 0);
  516.  
  517.                 lpfb->lpfnToolbar = (WNDPROC)SetWindowLong (lpfb->hwndTb,
  518.                                         GWL_WNDPROC,
  519.                                         (LONG)ToolbarSubclassProc);
  520.  
  521.                 lpfb->hwndFont = CreateWindow ((LPCTSTR)rgchComboBox,
  522.                                         NULL,
  523.                                         WS_CHILD | WS_VSCROLL | CBS_DROPDOWN | CBS_SORT | WS_VISIBLE,
  524.                                         0, 3, cxName, rcTb.bottom * 5,
  525.                                         lpfb->hwndTb,
  526.                                         (HMENU) ID_Font,
  527.                                         lpscd->hinst,
  528.                                         NULL);
  529.  
  530.                 CTL3D_SubclassCtl (lpCtl3D, lpfb->hwndFont);
  531.  
  532.                 SetWindowFont (lpfb->hwndFont, lpfb->hfnt, TRUE);
  533.                 ComboBox_SetExtendedUI (lpfb->hwndFont, TRUE);
  534.                 FillFontNames (lpfb->hwndFont);
  535.  
  536.                 lpfb->hwndSize = CreateWindow ((LPCTSTR)rgchComboBox,
  537.                                         NULL,
  538.                                         WS_CHILD | WS_VSCROLL | CBS_DROPDOWN | WS_VISIBLE,
  539.                                         cxName + 8, 3, cxSize, rcTb.bottom * 5,
  540.                                         lpfb->hwndTb,
  541.                                         (HMENU) ID_FontSize,
  542.                                         lpscd->hinst,
  543.                                         NULL);
  544.  
  545.                 CTL3D_SubclassCtl (lpCtl3D, lpfb->hwndSize);
  546.  
  547.                 SetWindowFont (lpfb->hwndSize, lpfb->hfnt, TRUE);
  548.                 ComboBox_SetExtendedUI (lpfb->hwndSize, TRUE);
  549.                 ComboBox_LimitText (lpfb->hwndSize, cchSizeMax);
  550.                 FillSizes (lpfb);
  551.  
  552.                 UpdateFormatBar (lpfb->hwndFrame);
  553.                 ShowWindow (lpfb->hwndFrame, SW_SHOW);
  554.                 ShowWindow (lpfb->hwndTb, SW_SHOW);
  555.             }
  556.         }
  557.     }
  558.     *lppfb = lpfb;
  559.     DebugTraceSc (ScCreateToolbar(), (lpfb->hwndFrame ? S_OK : MAPI_E_CALL_FAILED));
  560.     return (lpfb->hwndFrame ? S_OK : MAPI_E_CALL_FAILED);
  561. }
  562.  
  563. STDMETHODIMP_(BOOL)
  564. FDoRTFCommand (HWND hwnd, UINT id, UINT code)
  565. {
  566.     LPFORMATBAR lpfb = (LPFORMATBAR)(GetWindowLong (hwnd, GWL_USERDATA));
  567.     DWORD dw;
  568.     RECT rc;
  569.     UINT iSel;
  570.  
  571.     switch (id)
  572.     {
  573.       case ID_Font:
  574.  
  575.         if (code == CBN_SELENDOK)
  576.         {
  577.             FillSizes (lpfb);
  578.             iSel = ComboBox_GetCurSel (lpfb->hwndFont);
  579.             lpfb->cf.dwMask = CFM_FACE | CFM_CHARSET;
  580.             ComboBox_GetLBText (lpfb->hwndFont, iSel, lpfb->cf.szFaceName);
  581.             dw = ComboBox_GetItemData (lpfb->hwndFont, iSel);
  582.             lpfb->cf.bPitchAndFamily = (BYTE)(dw >>= 16) & 0xFF;
  583.             lpfb->cf.bCharSet = (BYTE)(dw >>= 8) & 0xFF;
  584.             SendMessage (lpfb->hwndEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)(LPVOID)&lpfb->cf);
  585.             UpdateFormatBar (lpfb->hwndFrame);
  586.             SetFocus (lpfb->hwndEdit);
  587.         }
  588.         break;
  589.  
  590.       case ID_FontSize:
  591.  
  592.         if (code == CBN_SELENDOK)
  593.         {
  594.             UINT i;
  595.             TCHAR rgch[cchSizeMax];
  596.  
  597.             rgch[0] = 0;
  598.             lpfb->cf.dwMask = CFM_SIZE;
  599.             ComboBox_GetLBText (lpfb->hwndSize,
  600.                         ComboBox_GetCurSel (lpfb->hwndSize),
  601.                         rgch);
  602.             for (lpfb->cf.yHeight = 0, i = 0; rgch[i]; i++)
  603.                 lpfb->cf.yHeight = (lpfb->cf.yHeight * 10) + (rgch[i] - '0');
  604.             lpfb->cf.yHeight *= 20;
  605.             SendMessage (lpfb->hwndEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)(LPVOID)&lpfb->cf);
  606.             UpdateFormatBar (lpfb->hwndFrame);
  607.             SetFocus (lpfb->hwndEdit);
  608.         }
  609.         break;
  610.         break;
  611.  
  612.       case ID_Color:
  613.  
  614.         if (lpfb->hdc = GetDC (lpfb->hwndTb))
  615.         {
  616.             SendMessage (lpfb->hwndTb, TB_GETITEMRECT, 1, (LPARAM) &rc);
  617.             MapWindowPoints (lpfb->hwndTb, NULL, (LPPOINT)&rc, 2);
  618.             TrackPopupMenu (lpfb->hmnuColor, TPM_LEFTALIGN | TPM_LEFTBUTTON,
  619.                     rc.left, rc.bottom + 2, 0, hwnd, NULL);
  620.             ReleaseDC (lpfb->hwndTb, lpfb->hdc);
  621.         }
  622.         break;
  623.  
  624.       case ID_ColorAuto:
  625.       case ID_ColorBlack:
  626.       case ID_ColorMaroon:
  627.       case ID_ColorGreen:
  628.       case ID_ColorOlive:
  629.       case ID_ColorBlue:
  630.       case ID_ColorPurple:
  631.       case ID_ColorTeal:
  632.       case ID_ColorGray:
  633.       case ID_ColorSilver:
  634.       case ID_ColorRed:
  635.       case ID_ColorLime:
  636.       case ID_ColorYellow:
  637.       case ID_ColorNavy:
  638.       case ID_ColorFuchia:
  639.       case ID_ColorAqua:
  640.       case ID_ColorWhite:
  641.  
  642.         lpfb->cf.dwMask = CFM_COLOR;
  643.         lpfb->cf.dwEffects &= ~CFE_AUTOCOLOR;
  644.         lpfb->cf.dwEffects |= (id == ID_ColorAuto) ? CFE_AUTOCOLOR : 0;
  645.         lpfb->cf.crTextColor = (COLORREF)rgrgb[id - ID_Color - 1];
  646.         SendMessage (lpfb->hwndEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)(LPVOID)&lpfb->cf);
  647.         break;
  648.  
  649.       case ID_Bold:
  650.       case ID_Italic:
  651.       case ID_Underline:
  652.  
  653.         DebugTrace ("dwMask before: 0x%08lX\n", lpfb->cf.dwMask);
  654.         DebugTrace ("dwEffects before: 0x%08lX\n", lpfb->cf.dwEffects);
  655.         lpfb->cf.dwMask = rgdwEffect[id - ID_Bold];
  656.         lpfb->cf.dwEffects ^= rgdwEffect[id - ID_Bold];
  657.         DebugTrace ("dwMask after: 0x%08lX\n", lpfb->cf.dwMask);
  658.         DebugTrace ("dwEffects after: 0x%08lX\n", lpfb->cf.dwEffects);
  659.         SendMessage (lpfb->hwndEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)(LPVOID)&lpfb->cf);
  660.         break;
  661.  
  662.       case ID_Indent:
  663.       case ID_Collapse:
  664.  
  665.         lpfb->pf.dwMask = PFM_STARTINDENT;
  666.         lpfb->pf.dxStartIndent += ((id == ID_Indent) ? cxIndent : -cxIndent);
  667.         SendMessage (lpfb->hwndEdit, EM_SETPARAFORMAT, 0, (LPARAM)(LPVOID)&lpfb->pf);
  668.         break;
  669.  
  670.       case ID_Left:
  671.       case ID_Center:
  672.       case ID_Right:
  673.  
  674.         lpfb->pf.dwMask = PFM_ALIGNMENT;
  675.         lpfb->pf.wAlignment = rgwAlign[id - ID_Left];
  676.         SendMessage (lpfb->hwndEdit, EM_SETPARAFORMAT, 0, (LPARAM)(LPVOID)&lpfb->pf);
  677.         break;
  678.  
  679.       case ID_Bullet:
  680.  
  681.         lpfb->pf.dwMask = PFM_NUMBERING | PFM_OFFSET;
  682.         if (lpfb->pf.wNumbering != PFN_BULLET)
  683.         {
  684.             lpfb->pf.wNumbering = PFN_BULLET;
  685.             lpfb->pf.dxOffset = cxIndent;
  686.         }
  687.         else
  688.         {
  689.             lpfb->pf.wNumbering = 0;
  690.             lpfb->pf.dxOffset = 0;
  691.         }
  692.         SendMessage (lpfb->hwndEdit, EM_SETPARAFORMAT, 0, (LPARAM)(LPVOID)&lpfb->pf);
  693.         break;
  694.  
  695.       default:
  696.  
  697.         return FALSE;
  698.     }
  699.     return TRUE;
  700. }
  701.  
  702. void
  703. UpdateFormatBar (HWND hwnd)
  704. {
  705.     LPFORMATBAR lpfb = (LPFORMATBAR)(GetWindowLong (hwnd, GWL_USERDATA));
  706.     TCHAR rgch[cchSizeMax];
  707.     UINT i;
  708.  
  709.     SendMessage (lpfb->hwndEdit, EM_GETCHARFORMAT, TRUE, (LPARAM)(LPVOID)&lpfb->cf);
  710.     DebugTrace ("SMH: updating formatbar: format: %s%s%s\n",
  711.         (lpfb->cf.dwEffects & rgdwEffect[0]) ? "BOLD, " : "",
  712.         (lpfb->cf.dwEffects & rgdwEffect[1]) ? "ITALIC, " : "",
  713.         (lpfb->cf.dwEffects & rgdwEffect[2]) ? "UNDERLINED" : "");
  714.     DebugTrace ("SMH: updating formatbar: current font: %s\n", lpfb->cf.szFaceName);
  715.     DebugTrace ("SMH: updating formatbar: current font height: %d\n", lpfb->cf.yHeight);
  716.     DebugTrace ("SMH: updating formatbar: current font size: %d\n", FontSize (lpfb->cf.yHeight));
  717.     DebugTrace ("SMH: updating formatbar: color: 0x%2X (r), 0x%2X (g), 0x%2x (b)\n",
  718.         GetRValue (lpfb->cf.crTextColor),
  719.         GetGValue (lpfb->cf.crTextColor),
  720.         GetBValue (lpfb->cf.crTextColor));
  721.         
  722.     for (i = ID_Bold; i <= ID_Underline; i++)
  723.         SendMessage (lpfb->hwndTb, TB_CHECKBUTTON, i,
  724.             MAKELONG (lpfb->cf.dwEffects & rgdwEffect[i - ID_Bold], 0));
  725.  
  726.     i = ComboBox_FindString (lpfb->hwndFont, -1, lpfb->cf.szFaceName);
  727.     if (i != (UINT)ComboBox_GetCurSel (lpfb->hwndFont))
  728.     {
  729.         ComboBox_SetCurSel (lpfb->hwndFont, i);
  730.         ComboBox_SetText (lpfb->hwndFont, lpfb->cf.szFaceName);
  731.     }
  732.  
  733.     wsprintf (rgch, "%d", FontSize (lpfb->cf.yHeight));
  734.     i = (UINT)ComboBox_FindStringExact (lpfb->hwndSize, -1, rgch);
  735.     if ((i != CB_ERR) || (i != (UINT)ComboBox_GetCurSel (lpfb->hwndSize)))
  736.         ComboBox_SetCurSel (lpfb->hwndSize, i);
  737.     ComboBox_SetText (lpfb->hwndSize, rgch);
  738.     return;
  739. }
  740.