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.
 
 
 
 
 
 

1976 lines
55 KiB

/*
* f m t b a r . c p p
*
* Format Bar based on IOleCommandTarget
* Owner: brettm / a-mli
*
*/
#include <pch.hxx>
#include "dllmain.h"
#include <shfusion.h>
#include "demand.h"
#include "resource.h"
#include "util.h"
#include "mshtml.h"
#include "mshtmhst.h"
#include "mshtmcid.h"
#include "docobj.h"
#include "fmtbar.h"
#include "strconst.h"
#include "comctrlp.h"
#include <shlguidp.h>
/*
* WS_EX_LAYOUTRTL ported from winuser.h
*/
#if WINVER < 0X0500
#define WS_EX_LAYOUTRTL 0x00400000L // Right to left mirroring
#endif // WS_EX_LAYOUTRTL
/*
* m a c r o s
*/
#define GETINDEX(m) ((DWORD)((((m & 0xff000000) >> 24) & 0x000000ff)))
#define MAKEINDEX(b, l) (((DWORD)l & 0x00ffffff) | ((DWORD)b << 24))
/*
* c o n s t a n t s
*/
#define cxButtonSep 8
#define dxToolbarButton 16
#define COMBOBUFSIZE 64
#define dxFormatFontBitmap 20
#define dyFormatFontBitmap 12
#define NFONTSIZES 7
#define TEMPBUFSIZE 30
#define CYDROPDOWNEXPANDRATIO 8
#define SIZETEXTLIMIT 8
#define cxDUName 100
#define cyToolbarOffset 2
#define idcCoolbar 45
// FormatBar stuff
enum
{
itbFormattingTag,
itbFormattingBold,
itbFormattingItalic,
itbFormattingUnderline,
itbFormattingColor,
itbFormattingNumbers,
itbFormattingBullets,
itbFormattingDecreaseIndent,
itbFormattingIncreaseIndent,
itbFormattingLeft,
itbFormattingCenter,
itbFormattingRight,
itbFormattingJustify,
itbFormattingInsertHLine,
itbFormattingInsertLink,
itbFormattingInsertImage,
ctbFormatting
};
// FormatBar Paragraph direction stuff
enum
{
itbFormattingBlockDirLTR = ctbFormatting,
itbFormattingBlockDirRTL,
};
/*
* t y p e d e f s
*/
/*
* g l o b a l d a t a
*/
static const TCHAR c_szComboBox[] = "ComboBox",
c_szFmtBarClass[] = "MimeEdit_FormatBar",
c_szThis[] = "OE_This";
/*
* Color table for dropdown on toolbar. Matches COMMDLG colors
* exactly.
*/
static DWORD rgrgbColors[] =
{
RGB( 0, 0, 0), // "BLACK"},
RGB(128, 0, 0), // "MAROON"},
RGB( 0, 128, 0), // "GREEN"},
RGB(128, 128, 0), // "OLIVE"},
RGB( 0, 0, 128), // "NAVY"},
RGB(128, 0, 128), // "PURPLE"},
RGB( 0, 128, 128), // "TEAL"},
RGB(128, 128, 128), // "GREY"},
RGB(192, 192, 192), // "SILVER"},
RGB(255, 0, 0), // "RED"},
RGB( 0, 255, 0), // "LIME"},
RGB(255, 255, 0), // "YELLOW"},
RGB( 0, 0, 255), // "BLUE"},
RGB(255, 0, 255), // "FUSCHIA"},
RGB( 0, 255, 255), // "AQUA"},
RGB(255, 255, 255) // "WHITE"}
};
static TBBUTTON rgtbbutton[] =
{
{ itbFormattingTag, idmFmtTag,
TBSTATE_ENABLED, TBSTYLE_DROPDOWN, {0}, 0L, -1 },
{ cxButtonSep, 0L,
TBSTATE_ENABLED, TBSTYLE_SEP, {0}, 0L, -1 },
{ itbFormattingBold, idmFmtBold,
TBSTATE_ENABLED, TBSTYLE_CHECK, {0}, 0L, -1 },
{ itbFormattingItalic, idmFmtItalic,
TBSTATE_ENABLED, TBSTYLE_CHECK, {0}, 0L, -1 },
{ itbFormattingUnderline, idmFmtUnderline,
TBSTATE_ENABLED, TBSTYLE_CHECK, {0}, 0L, -1 },
{ itbFormattingColor, idmFmtColor,
TBSTATE_ENABLED, TBSTYLE_DROPDOWN, {0}, 0L, -1 },
{ cxButtonSep, 0L,
TBSTATE_ENABLED, TBSTYLE_SEP, {0}, 0L, -1 },
{ itbFormattingNumbers, idmFmtNumbers,
TBSTATE_ENABLED, TBSTYLE_CHECK, {0}, 0L, -1 },
{ itbFormattingBullets, idmFmtBullets,
TBSTATE_ENABLED, TBSTYLE_CHECK, {0}, 0L, -1 },
{ itbFormattingDecreaseIndent, idmFmtDecreaseIndent,
TBSTATE_ENABLED, TBSTYLE_BUTTON, {0}, 0L, -1 },
{ itbFormattingIncreaseIndent, idmFmtIncreaseIndent,
TBSTATE_ENABLED, TBSTYLE_BUTTON, {0}, 0L, -1 },
{ cxButtonSep, 0L,
TBSTATE_ENABLED, TBSTYLE_SEP, {0}, 0L, -1 },
{ itbFormattingLeft, idmFmtLeft,
TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, {0}, 0L, -1 },
{ itbFormattingCenter, idmFmtCenter,
TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, {0}, 0L, -1 },
{ itbFormattingRight, idmFmtRight,
TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, {0}, 0L, -1 },
{ itbFormattingJustify, idmFmtJustify,
TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, {0}, 0L, -1 },
{ cxButtonSep, 0L,
TBSTATE_ENABLED, TBSTYLE_SEP, {0}, 0L, -1 },
{ itbFormattingInsertHLine, idmFmtInsertHLine,
TBSTATE_ENABLED, TBSTYLE_BUTTON, {0}, 0L, -1 },
{ itbFormattingInsertLink, idmEditLink,
TBSTATE_ENABLED, TBSTYLE_BUTTON, {0}, 0L, -1 },
{ itbFormattingInsertImage, idmInsertImage,
TBSTATE_ENABLED, TBSTYLE_BUTTON, {0}, 0L, -1 }
};
static TBBUTTON rgtbblkdirbutton[] =
{
{ itbFormattingBlockDirLTR, idmFmtBlockDirLTR,
TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, {0}, 0L, -1 },
{ itbFormattingBlockDirRTL, idmFmtBlockDirRTL,
TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, {0}, 0L, -1 },
{ cxButtonSep, 0L,
TBSTATE_ENABLED, TBSTYLE_SEP, {0}, 0L, -1 }
};
#define ctbbutton (sizeof(rgtbbutton) / sizeof(TBBUTTON))
/*
* p r o t o t y p e s
*/
HRESULT ColorMenu_Show(HMENU hmenuColor, HWND hwndParent, POINT pt, COLORREF *pclrf);
void Color_WMDrawItem(HWND hwnd, LPDRAWITEMSTRUCT pdis);
void Color_WMMeasureItem(HWND hwnd, HDC hdc, LPMEASUREITEMSTRUCT pmis);
INT GetColorIndex(INT rbg);
HFONT hFontGetMenuFont(HWND hwnd);
/*
* f u n c t i o n s
*/
CFmtBar::CFmtBar(BOOL fSep)
{
m_cRef=1;
m_hwnd = NULL;
m_hwndToolbar = NULL;
m_hwndName = NULL;
m_hwndSize = NULL;
m_wndprocEdit = NULL;
m_wndprocNameComboBox = NULL;
m_wndprocSizeComboBox = NULL;
m_hbmName = NULL;
m_hmenuColor = NULL;
m_hmenuTag = NULL;
m_fDestroyTagMenu = 1;
m_pCmdTarget=0;
m_fVisible = 0;
m_fSep = !!fSep;
m_himlHot = NULL;
m_himl = NULL;
}
CFmtBar::~CFmtBar()
{
if (m_hbmName)
DeleteObject(m_hbmName);
if (m_hmenuColor)
DestroyMenu(m_hmenuColor);
if (m_hmenuTag && !!m_fDestroyTagMenu)
DestroyMenu(m_hmenuTag);
_FreeImageLists();
}
ULONG CFmtBar::AddRef()
{
return ++m_cRef;
}
ULONG CFmtBar::Release()
{
ULONG cRef=--m_cRef;
if(m_cRef==0)
delete this;
return cRef;
}
HRESULT CreateColorMenu(ULONG idmStart, HMENU* pMenu)
{
DWORD irgb;
DWORD mniColor;
if(pMenu == NULL)
return E_INVALIDARG;
*pMenu = CreatePopupMenu();
if (*pMenu == NULL)
return E_OUTOFMEMORY;
// Add the COLORREF version of each entry into the menu
for (irgb = 0, mniColor=idmStart; irgb < sizeof(rgrgbColors)/sizeof(DWORD); ++irgb, ++mniColor)
AppendMenu(*pMenu, MF_ENABLED|MF_OWNERDRAW, mniColor, (LPCSTR)IntToPtr(MAKEINDEX(irgb, rgrgbColors[irgb])));
return S_OK;
}
LRESULT CALLBACK CFmtBar::ExtWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
LPFORMATBAR pFmtBar=0;
if (msg==WM_NCCREATE)
{
pFmtBar=(CFmtBar *)((LPCREATESTRUCT)lParam)->lpCreateParams;
if(!pFmtBar)
return -1;
return (pFmtBar->OnNCCreate(hwnd)==S_OK);
}
pFmtBar = (LPFORMATBAR)GetWndThisPtr(hwnd);
if (pFmtBar)
return pFmtBar->WndProc(hwnd, msg, wParam, lParam);
else
return DefWindowProc(hwnd, msg, wParam, lParam);
}
extern BOOL g_fCanEditBiDi;
HRESULT CFmtBar::OnNCCreate(HWND hwnd)
{
RECT rc;
HFONT hfontOld,
hfontToolbar;
HWND hwndEdit,
hwndToolTips;
BOOL fRet;
HDC hdc,
hdcParent;
TEXTMETRIC tm;
INT yPos;
INT cxDownButton;
INT cxName;
INT cxSize,
cx;
INT cyToolbarButton;
INT cyDropDownRollHeight;
INT cyExpandedList;
const POINT pt = {5, 5};
LONG lstyle;
TOOLINFO ti;
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this);
m_hwnd=hwnd;
AddRef();
m_hwndRebar = CreateWindowEx(0, REBARCLASSNAME, NULL,
WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN |
WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NOPARENTALIGN,
0, 0, 100, 136, m_hwnd, (HMENU) idcCoolbar, g_hInst, NULL);
if (!m_hwndRebar)
return E_OUTOFMEMORY;
SendMessage(m_hwndRebar, RB_SETTEXTCOLOR, 0, (LPARAM)GetSysColor(COLOR_BTNTEXT));
SendMessage(m_hwndRebar, RB_SETBKCOLOR, 0, (LPARAM)GetSysColor(COLOR_BTNFACE));
//SendMessage(m_hwndRebar, RB_SETEXTENDEDSTYLE, RBS_EX_OFFICE9, RBS_EX_OFFICE9);
SendMessage(m_hwndRebar, CCM_SETVERSION, COMCTL32_VERSION, 0);
// [a-msadek]; Fix for bug#55069
// DO NOT remove CCS_TOP from creation styles below
// It is a default style and toolbar WinProc will addit any way durin
// WM_NCCREATE processing. However, it will cause WM_STYLECHANGING to be sent
// Due to a bug in SetWindowPos() for a mirrored window, it will never return from seding
// messages calling a stack overflow
// No need to put it only for a mirrored window since it will be added any way
// Look @ comctl32\toolbar.c, functions ToolbarWndProc() and TBAutoSize();
m_hwndToolbar = CreateWindowEx(WS_EX_TOOLWINDOW, TOOLBARCLASSNAME, NULL,
WS_CHILD|WS_CLIPCHILDREN|WS_VISIBLE|CCS_TOP|CCS_NOPARENTALIGN|CCS_NODIVIDER|
TBSTYLE_TOOLTIPS|TBSTYLE_FLAT,
0, 0, 0, 0, m_hwndRebar, NULL,
g_hInst, NULL);
if (!m_hwndToolbar)
return E_OUTOFMEMORY;
SendMessage(m_hwndToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
SendMessage(m_hwndToolbar, TB_ADDBUTTONS, (WPARAM)ctbbutton, (LPARAM)rgtbbutton);
SendMessage(m_hwndToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(dxToolbarButton, dxToolbarButton));
_SetToolbarBitmaps();
// add BiDi direction buttons
if(g_fCanEditBiDi)
{
SendMessage(m_hwndToolbar, TB_INSERTBUTTON, ctbbutton - 3, (LPARAM) (LPVOID) &rgtbblkdirbutton[2]);
SendMessage(m_hwndToolbar, TB_INSERTBUTTON, ctbbutton - 3, (LPARAM) (LPVOID) &rgtbblkdirbutton[1]);
SendMessage(m_hwndToolbar, TB_INSERTBUTTON, ctbbutton - 3, (LPARAM) (LPVOID) &rgtbblkdirbutton[0]);
SendMessage(m_hwndToolbar, TB_AUTOSIZE, (WPARAM)0, (LPARAM)0);
}
hdcParent = GetDC(GetParent(hwnd));
if (!hdcParent)
return E_OUTOFMEMORY;
hdc = CreateCompatibleDC(hdcParent);
ReleaseDC(GetParent(hwnd), hdcParent);
if (!hdc)
return E_OUTOFMEMORY;
hfontToolbar = (HFONT) SendMessage(m_hwndToolbar, WM_GETFONT, 0, 0);
// Get font metrics (of System font) so that we can properly scale the
// format bar layout
hfontOld = (HFONT)SelectObject(hdc, hfontToolbar);
GetTextMetrics(hdc, &tm);
cxDownButton = GetSystemMetrics(SM_CXVSCROLL) + GetSystemMetrics(SM_CXDLGFRAME);
cxName = (cxDUName * tm.tmAveCharWidth) / 4 + cxDownButton;
cxSize = XFontSizeCombo(hdc) + cxDownButton;
SelectObject(hdc, hfontOld);
DeleteDC(hdc);
// set the size of the formatbar based on the size of the toolbar plus 2 pixels padding
GetClientRect(m_hwndToolbar, &rc);
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);
// Determine how tall the buttons are so we can size our other controls
// accordingly
SendMessage(m_hwndToolbar, TB_GETITEMRECT, 1, (LPARAM) &rc);
cyToolbarButton = rc.bottom - rc.top + 1;
// Figure out size of expanded dropdown lists
cyExpandedList = CYDROPDOWNEXPANDRATIO * cyToolbarButton;
// Get the ToolTips window handle
hwndToolTips = (HWND) SendMessage(m_hwndToolbar, TB_GETTOOLTIPS, 0, 0);
m_hwndName = CreateWindow(c_szComboBox, NULL,
WS_CHILD | WS_VSCROLL | CBS_DROPDOWN |
CBS_SORT | CBS_HASSTRINGS |
CBS_OWNERDRAWFIXED |WS_VISIBLE,
0, 0, cxName, cyExpandedList,
m_hwndToolbar,
(HMENU) idmFmtFont, g_hLocRes, NULL);
if (!m_hwndName)
return E_OUTOFMEMORY;
ComboBox_SetExtendedUI(m_hwndName, TRUE);
// Load up the mini-icons for TrueType or Printer font
m_hbmName = LoadDIBBitmap(idbFormatBarFont);
if (!m_hbmName)
return E_OUTOFMEMORY;
// Compute the right edge of the combobox
SetWindowFont(m_hwndName, hfontToolbar, TRUE);
// The Size
m_hwndSize = CreateWindow(c_szComboBox, NULL,
WS_CHILD | WS_VSCROLL | CBS_DROPDOWNLIST |
WS_VISIBLE,
cxName + cxButtonSep, 0, cxSize, cyExpandedList,
m_hwndToolbar,
(HMENU) idmFmtSize, g_hLocRes, NULL);
if (!m_hwndSize)
return E_OUTOFMEMORY;
m_hwndTT = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL, 0,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, (HMENU) NULL, g_hInst, NULL);
if (!m_hwndTT)
return E_OUTOFMEMORY;
ZeroMemory(&ti, sizeof(TOOLINFO));
ti.cbSize = sizeof(TOOLINFO);
ti.uFlags = TTF_IDISHWND | TTF_TRANSPARENT | TTF_TRACK | TTF_ABSOLUTE;
ti.hwnd = m_hwndName;
ti.uId = (ULONG_PTR)m_hwndName;
SendMessage(m_hwndTT, TTM_ADDTOOL, 0, (LPARAM)&ti);
SendMessage(m_hwndTT, WM_SETFONT, (WPARAM)(HFONT)SendMessage(m_hwndToolbar, WM_GETFONT, 0, 0), 0);
ComboBox_SetExtendedUI(m_hwndSize, TRUE);
SetWindowFont(m_hwndSize, hfontToolbar, TRUE);
// font sizes up to 4 digits are allowed
ComboBox_LimitText(m_hwndSize, SIZETEXTLIMIT);
// The color popup menu (initially empty)
// Set the rolled-up heights of the combo boxes to all be the same
cyDropDownRollHeight = LOWORD(SendMessage(m_hwndSize, CB_GETITEMHEIGHT, (WPARAM)-1, 0));
// hwndName is ownerdrawn
SendMessage(m_hwndName, CB_SETITEMHEIGHT, (WPARAM)-1, cyDropDownRollHeight);
// Determine how tall the toolbar is so we can center the comboboxes
GetClientRect(m_hwndToolbar, &rc);
// Get size of toolbar window
yPos = rc.bottom;
// Get size of combobox
GetClientRect(m_hwndSize, &rc);
yPos = (yPos - rc.bottom) / 2;
// We have a mirroring bug in GetWindowRect
// It will give wrong cocordinates causing combos to go outside the screen
// Ignore y-positioning in this case
if(!(GetWindowLong(m_hwndToolbar, GWL_EXSTYLE) & WS_EX_LAYOUTRTL))
{
GetWindowRect(m_hwndName, &rc);
MapWindowPoints(NULL, hwnd, (LPPOINT)&rc, 2);
MoveWindow(m_hwndName, rc.left, yPos, rc.right-rc.left, rc.bottom-rc.top, FALSE);
GetWindowRect(m_hwndSize, &rc);
MapWindowPoints(NULL, hwnd, (LPPOINT)&rc, 2);
MoveWindow(m_hwndSize, rc.left, yPos, rc.right-rc.left, rc.bottom-rc.top, FALSE);
}
hwndEdit = ::GetWindow(m_hwndName, GW_CHILD);
// Add tooltips for the controls we just added
AddToolTip(hwndToolTips, m_hwndName, idsTTFormattingFont);
AddToolTip(hwndToolTips, m_hwndSize, idsTTFormattingSize);
AddToolTip(hwndToolTips, hwndEdit, idsTTFormattingFont);
// Subclass the comboboxes and their edit controls
// Do the name edit control first
m_wndprocEdit = SubclassWindow(hwndEdit, EditSubProc);
m_wndprocNameComboBox = SubclassWindow(m_hwndName, ComboBoxSubProc);
m_wndprocSizeComboBox = SubclassWindow(m_hwndSize, ComboBoxSubProc);
// give the control This pointers
SetProp(m_hwndName, c_szThis, (LPVOID)this);
SetProp(m_hwndSize, c_szThis, (LPVOID)this);
SetProp(hwndEdit, c_szThis, (LPVOID)this);
GetClientRect(m_hwndToolbar, &rc);
cx = cxName + cxSize + cxButtonSep * 2;
REBARBANDINFO rbbi;
POINT ptIdeal = {0};
SendMessage(m_hwndToolbar, TB_GETIDEALSIZE, FALSE, (LPARAM)&ptIdeal);
ZeroMemory(&rbbi, sizeof(rbbi));
rbbi.cbSize = sizeof(REBARBANDINFO);
rbbi.fMask = RBBIM_SIZE | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE | RBBIM_STYLE;
rbbi.fStyle = RBBS_USECHEVRON;
rbbi.cx = 0;
rbbi.hwndChild = m_hwndToolbar;
rbbi.cxMinChild = 0;
rbbi.cyMinChild = rc.bottom;
rbbi.cxIdeal = ptIdeal.x + cx;
SendMessage(m_hwndRebar, RB_INSERTBAND, (UINT)-1, (LPARAM)(LPREBARBANDINFO)&rbbi);
// Indent the toolbar buttons for the comboboxes
SendMessage(m_hwndToolbar, TB_SETINDENT, cx, 0);
// Load up the names of the fonts and colors
FillFontNames();
FillSizes();
return S_OK;
}
void CFmtBar::OnNCDestroy()
{
SetWindowLongPtr(m_hwnd, GWLP_USERDATA, 0);
m_hwnd=0;
Release();
}
LRESULT CALLBACK CFmtBar::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_DESTROY:
// unsubclass the windows
if (m_wndprocEdit)
{
SubclassWindow(::GetWindow(m_hwndName, GW_CHILD), m_wndprocEdit);
RemoveProp(::GetWindow(m_hwndName, GW_CHILD), c_szThis);
}
if (m_wndprocNameComboBox)
{
SubclassWindow(m_hwndName, m_wndprocNameComboBox);
RemoveProp(m_hwndName, c_szThis);
}
if (m_wndprocSizeComboBox)
{
SubclassWindow(m_hwndSize, m_wndprocSizeComboBox);
RemoveProp(m_hwndSize, c_szThis);
}
DestroyWindow(m_hwndTT);
m_hwndTT=NULL;
break;
case WM_NCDESTROY:
OnNCDestroy();
break;
case WM_COMMAND:
if(OnWMCommand(GET_WM_COMMAND_HWND(wParam, lParam),
GET_WM_COMMAND_ID(wParam, lParam),
GET_WM_COMMAND_CMD(wParam, lParam))==S_OK)
return 0;
break;
case WM_PAINT:
if (m_fSep)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rc;
hdc=BeginPaint(hwnd, &ps);
if (hdc)
{
GetClientRect(hwnd, &rc);
rc.top = rc.bottom-3;
//rc.bottom+=1;
DrawEdge(hdc, &rc, BDR_RAISEDOUTER, BF_BOTTOM);
EndPaint(hwnd, &ps);
}
return 0;
}
break;
case WM_NOTIFY:
WMNotify(wParam, (NMHDR*)lParam);
return 0;
case WM_SIZE:
{
RECT rc;
GetClientRect(m_hwndRebar, &rc);
// resize the width of the toolbar
if(rc.right != (INT)LOWORD(lParam))
SetWindowPos(m_hwndRebar, NULL, 0, cyToolbarOffset, LOWORD(lParam), HIWORD(lParam), SWP_NOZORDER|SWP_NOACTIVATE);
}
break;
case WM_DRAWITEM:
OnDrawItem((LPDRAWITEMSTRUCT)lParam);
break;
case WM_SYSCOLORCHANGE:
_SetToolbarBitmaps();
UpdateRebarBandColors(m_hwndRebar);
// fall thro'
case WM_WININICHANGE:
case WM_DISPLAYCHANGE:
case WM_QUERYNEWPALETTE:
case WM_PALETTECHANGED:
SendMessage(m_hwndRebar, msg, wParam, lParam);
break;
case WM_MEASUREITEM:
OnMeasureItem((LPMEASUREITEMSTRUCT)lParam);
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
HRESULT CFmtBar::Init(HWND hwndParent, int idDlgItem)
{
// stuff these values. We don't create the formatbar until the first call to Show()
// to allow better perf.
m_hwndParent = hwndParent;
m_idd = idDlgItem;
return S_OK;
}
// displays the colorpopup menu at the specified point. if clrf if NULL, then no clrf is returned
// but instead the appropriate WM_COMMAND is dispatched to the parent window
HRESULT ColorMenu_Show(HMENU hmenuColor, HWND hwndParent, POINT pt, COLORREF *pclrf)
{
HRESULT hr=NOERROR;
int tpm=TPM_LEFTALIGN|TPM_LEFTBUTTON;
if(hmenuColor == NULL)
return E_INVALIDARG;
if(pclrf)
tpm|=TPM_RETURNCMD;
int id = TrackPopupMenu(hmenuColor, tpm,pt.x, pt.y, 0, hwndParent, NULL);
switch(id)
{
case 1:
return NOERROR;
case 0:
return E_FAIL;
case -1:
return MIMEEDIT_E_USERCANCEL;
case idmFmtColor1:
case idmFmtColor2:
case idmFmtColor3:
case idmFmtColor4:
case idmFmtColor5:
case idmFmtColor6:
case idmFmtColor7:
case idmFmtColor8:
case idmFmtColor9:
case idmFmtColor10:
case idmFmtColor11:
case idmFmtColor12:
case idmFmtColor13:
case idmFmtColor14:
case idmFmtColor15:
case idmFmtColor16:
AssertSz(pclrf, "this HAS to be set to get this id back...");
*pclrf=rgrgbColors[id-idmFmtColor1];
return NOERROR;
default:
AssertSz(0, "unexpected return from TrackPopupMenu");
}
return E_FAIL;
}
HRESULT CFmtBar::CheckColor()
{
HRESULT hr=E_FAIL;
INT iFound = -1, irgb;
VARIANTARG va;
if (!m_pCmdTarget)
return E_FAIL;
va.vt = VT_I4;
va.lVal = -1;
hr = m_pCmdTarget->Exec(&CMDSETID_Forms3,
IDM_FORECOLOR,
MSOCMDEXECOPT_DONTPROMPTUSER,
NULL, &va);
if(FAILED(hr))
goto error;
if(va.lVal == -1)
goto error;
iFound = GetColorIndex(va.lVal);
error:
CheckMenuRadioItem(m_hmenuColor, idmFmtColor1, idmFmtColor16, idmFmtColor1+iFound, MF_BYCOMMAND);
return hr;
}
INT GetColorIndex(INT rbg)
{
INT iFound = -1;
for (int irgb = 1; irgb < sizeof(rgrgbColors)/sizeof(DWORD); ++irgb)
if ((rbg&0x00ffffff) == (LONG)rgrgbColors[irgb])
{
iFound = irgb;
break;
}
return iFound;
}
HRESULT CFmtBar::HrInitTagMenu()
{
HRESULT hr=NOERROR;
int id;
int tpm=TPM_LEFTALIGN|TPM_LEFTBUTTON;
VARIANTARG va;
VARIANTARG *pvaIn=0;
TCHAR szBufMenu[MAX_PATH] = {0};
TCHAR szBufTag[MAX_PATH] = {0};
if (!m_pCmdTarget)
return E_FAIL;
if (!m_hmenuTag &&
FAILED(HrCreateTridentMenu(m_pCmdTarget, TM_TAGMENU, idmFmtTagFirst, idmFmtTagLast-idmFmtTagFirst, &m_hmenuTag)))
return E_FAIL;
hr = HrCheckTridentMenu(m_pCmdTarget, TM_TAGMENU, idmFmtTagFirst, idmFmtTagLast, m_hmenuTag);
return hr;
}
HRESULT CFmtBar::HrShowTagMenu(POINT pt)
{
HRESULT hr;
int tpm=TPM_LEFTALIGN|TPM_LEFTBUTTON;
hr = HrInitTagMenu();
if(FAILED(hr))
return hr;
TrackPopupMenu(m_hmenuTag, tpm, pt.x, pt.y, 0, m_hwnd, NULL);
return hr;
}
HMENU CFmtBar::hmenuGetStyleTagMenu()
{
HRESULT hr;
hr = HrInitTagMenu();
if(FAILED(hr))
return NULL;
m_fDestroyTagMenu = 0;
return m_hmenuTag;
}
// update toolbar buttons and font name/size combo boxes.
HRESULT CFmtBar::Update()
{
UINT uCmdID=0;
CHAR szBuf[COMBOBUFSIZE/2];
CHAR szBufbstrVal[COMBOBUFSIZE/2];
int i;
INT iPointSize=0, iHTMLSize=0;
HWND hwndEdit;
OLECMD rgCmds[]= {
{IDM_FONTNAME, 0},
{IDM_FONTSIZE, 0},
{IDM_FORECOLOR, 0},
{IDM_BOLD, 0},
{IDM_ITALIC, 0},
{IDM_UNDERLINE, 0},
{IDM_ORDERLIST, 0},
{IDM_UNORDERLIST, 0},
{IDM_JUSTIFYLEFT, 0},
{IDM_JUSTIFYRIGHT, 0},
{IDM_JUSTIFYCENTER, 0},
{IDM_JUSTIFYFULL, 0},
{IDM_BLOCKDIRLTR, 0},
{IDM_BLOCKDIRRTL, 0},
{IDM_OUTDENT, 0},
{IDM_INDENT, 0},
{IDM_HORIZONTALLINE, 0},
{IDM_HYPERLINK, 0},
{IDM_IMAGE, 0},
{IDM_BLOCKFMT, 0}};
int rgidm[] = { 0,
0,
idmFmtColor,
idmFmtBold,
idmFmtItalic,
idmFmtUnderline,
idmFmtNumbers,
idmFmtBullets,
idmFmtLeft,
idmFmtRight,
idmFmtCenter,
idmFmtJustify,
idmFmtBlockDirLTR,
idmFmtBlockDirRTL,
idmFmtDecreaseIndent,
idmFmtIncreaseIndent,
idmFmtInsertHLine,
idmEditLink,
idmInsertImage,
idmFmtTag};
ULONG uState;
BOOL fUIActive;
if (!m_hwnd) // no UI visible yet
return S_OK;
if (!m_pCmdTarget)
{
EnableWindow(m_hwndName, FALSE);
EnableWindow(m_hwndSize, FALSE);
for (i=2; i<sizeof(rgCmds)/sizeof(OLECMD); i++)
SendMessage(m_hwndToolbar, TB_SETSTATE, rgidm[i], MAKELONG(0, 0));
return S_OK;
}
HWND hwndFocus = GetFocus();
if (m_hwndToolbar == hwndFocus ||
(hwndFocus && m_hwndToolbar==GetParent(hwndFocus)) ||
(hwndFocus && GetParent(hwndFocus) && m_hwndToolbar==GetParent(GetParent(hwndFocus))) )
return S_OK;
fUIActive = FBodyHasFocus();
if (fUIActive)
m_pCmdTarget->QueryStatus(&CMDSETID_Forms3, sizeof(rgCmds)/sizeof(OLECMD), rgCmds, NULL);
EnableWindow(m_hwndName, fUIActive && (rgCmds[0].cmdf&OLECMDF_ENABLED));
EnableWindow(m_hwndSize, fUIActive && (rgCmds[1].cmdf&OLECMDF_ENABLED));
for (i=2; i<sizeof(rgCmds)/sizeof(OLECMD); i++)
{
uState=(rgCmds[i].cmdf&OLECMDF_LATCHED ? TBSTATE_PRESSED: 0)|
(rgCmds[i].cmdf&OLECMDF_ENABLED ? TBSTATE_ENABLED: 0);
SendMessage(m_hwndToolbar, TB_SETSTATE, rgidm[i], MAKELONG(uState, 0));
}
if (!fUIActive)
return S_OK;
// update font name combo box
VARIANTARG va;
va.vt = VT_BSTR;
va.bstrVal = NULL;
if (m_pCmdTarget->Exec(&CMDSETID_Forms3, IDM_FONTNAME, MSOCMDEXECOPT_DONTPROMPTUSER, NULL, &va) == S_OK)
{
hwndEdit = ::GetWindow(m_hwndName, GW_CHILD);
if (va.vt == VT_BSTR)
{
*szBuf = 0;
*szBufbstrVal = 0;
// we have a font-name, let's see if we need to update
ComboBox_GetText(hwndEdit, szBuf, COMBOBUFSIZE/2);
WideCharToMultiByte(CP_ACP, 0, (WCHAR*)va.bstrVal, -1, szBufbstrVal, COMBOBUFSIZE/2, NULL, NULL);
if (StrCmpI(szBufbstrVal, szBuf) != 0)
{
if(ComboBox_SelectString(m_hwndName, -1, szBufbstrVal) == -1)
ComboBox_SetText(hwndEdit, szBufbstrVal);
}
SafeSysFreeString(va.bstrVal);
}
else
ComboBox_SetText(hwndEdit, "");
}
// update font size combo box
va.vt = VT_I4;
va.lVal = 0;
if (m_pCmdTarget->Exec(&CMDSETID_Forms3, IDM_FONTSIZE, MSOCMDEXECOPT_DONTPROMPTUSER, NULL, &va)==S_OK &&
va.vt == VT_I4)
{
// font size if returned in the 1 to 7 range, for I4
// see if the font size has changed
*szBuf = 0;
if(ComboBox_GetText(m_hwndSize, szBuf, sizeof(szBuf)))
{
iPointSize = StrToInt(szBuf);
Assert(iPointSize>=8 && iPointSize<=36);
iHTMLSize = PointSizeToHTMLSize(iPointSize);
}
if(iHTMLSize != va.lVal)
ComboBox_SetCurSel(m_hwndSize, va.lVal-1);
}
else
ComboBox_SetCurSel(m_hwndSize, -1);
return S_OK;
}
HRESULT CFmtBar::OnWMCommand(HWND hwnd, int id, WORD wCmd)
{
UINT uCmdID=0;
VARIANTARG va;
VARIANTARG *pvaIn=0;
HRESULT hr = S_FALSE;
DWORD dwOpt=MSOCMDEXECOPT_DONTPROMPTUSER;
TOOLINFO ti;
ZeroMemory(&va, sizeof(va));
switch(wCmd)
{
case CBN_SELENDCANCEL:
// clear the tooltip
ZeroMemory(&ti, sizeof(TOOLINFO));
ti.cbSize = sizeof(TOOLINFO);
ti.hwnd = m_hwndName;
ti.uId = (ULONG_PTR)m_hwndName;
SendMessage(m_hwndTT, TTM_TRACKACTIVATE, FALSE, (LPARAM) &ti);
break;
case CBN_SELENDOK:
{
CHAR szBuf[COMBOBUFSIZE];
UINT uSel;
// clear the tooltip
ZeroMemory(&ti, sizeof(TOOLINFO));
ti.cbSize = sizeof(TOOLINFO);
ti.hwnd = m_hwndName;
ti.uId = (ULONG_PTR)m_hwndName;
SendMessage(m_hwndTT, TTM_TRACKACTIVATE, FALSE, (LPARAM) &ti);
if(idmFmtFont == id)
{
uCmdID = IDM_FONTNAME;
uSel = ComboBox_GetCurSel(m_hwndName);
// if(uSel < 0)
// return hr;
ComboBox_GetLBText(m_hwndName, uSel, szBuf);
va.vt = VT_BSTR;
pvaIn = &va;
hr=HrLPSZToBSTR(szBuf, &va.bstrVal);
if (FAILED(hr))
goto Cleanup;
}
else if(idmFmtSize == id)
{
// when setting font size use:
// VT_I4: for 1 - 7 range
// VT_STRING: for -2 -> +4 range.
uCmdID = IDM_FONTSIZE;
uSel = ComboBox_GetCurSel(m_hwndSize);
if(-1 == uSel)
return hr;
va.vt = VT_I4;
va.lVal = uSel + 1;
pvaIn = &va;
}
// set focus back to Trident, call HrUIActivate() after ComboBox operations.
SetBodyFocus();
hr = ExecCommand(uCmdID, dwOpt, pvaIn);
if(FAILED(hr))
goto Cleanup;
Cleanup:
if(va.vt == VT_BSTR && va.bstrVal != NULL)
SysFreeString(va.bstrVal);
return hr;
}
}
switch(id)
{
case idmFmtBold:
uCmdID=IDM_BOLD;
break;
case idmFmtItalic:
uCmdID=IDM_ITALIC;
break;
case idmFmtUnderline:
uCmdID=IDM_UNDERLINE;
break;
case idmAccelBullets:
case idmFmtBullets:
uCmdID=IDM_UNORDERLIST;
break;
case idmFmtNumbers:
uCmdID=IDM_ORDERLIST;
break;
case idmAccelJustify:
case idmFmtJustify:
uCmdID=IDM_JUSTIFYFULL;
break;
case idmAccelLeft:
case idmFmtLeft:
uCmdID=IDM_JUSTIFYLEFT;
break;
case idmAccelCenter:
case idmFmtCenter:
uCmdID=IDM_JUSTIFYCENTER;
break;
case idmAccelRight:
case idmFmtRight:
uCmdID=IDM_JUSTIFYRIGHT;
break;
case idmFmtBlockDirLTR:
uCmdID=IDM_BLOCKDIRLTR;
break;
case idmFmtBlockDirRTL:
uCmdID=IDM_BLOCKDIRRTL;
break;
case idmAccelDecreaseIndent:
case idmFmtDecreaseIndent:
uCmdID=IDM_OUTDENT;
break;
case idmAccelIncreaseIndent:
case idmFmtIncreaseIndent:
uCmdID=IDM_INDENT;
break;
case idmEditLink:
uCmdID=IDM_HYPERLINK;
dwOpt = MSOCMDEXECOPT_PROMPTUSER;
break;
case idmUnInsertLink:
uCmdID=IDM_UNLINK;
break;
case idmFmtInsertHLine:
uCmdID=IDM_HORIZONTALLINE;
break;
case idmInsertImage:
uCmdID=IDM_IMAGE;
dwOpt = MSOCMDEXECOPT_PROMPTUSER;
break;
case idmFmtColor1:
case idmFmtColor2:
case idmFmtColor3:
case idmFmtColor4:
case idmFmtColor5:
case idmFmtColor6:
case idmFmtColor7:
case idmFmtColor8:
case idmFmtColor9:
case idmFmtColor10:
case idmFmtColor11:
case idmFmtColor12:
case idmFmtColor13:
case idmFmtColor14:
case idmFmtColor15:
case idmFmtColor16:
{
uCmdID = IDM_FORECOLOR;
va.vt = VT_I4;
va.lVal = rgrgbColors[id-idmFmtColor1];
pvaIn = &va;
break;
}
}
if(id >= idmFmtTagFirst && id <= idmFmtTagLast) //style tags
{
TCHAR szBuf[MAX_PATH] = {0};
GetMenuString(m_hmenuTag, id, szBuf, MAX_PATH, MF_BYCOMMAND);
Assert(*szBuf);//should not be empty
hr=HrLPSZToBSTR(szBuf, &va.bstrVal);
if (FAILED(hr))
goto error;
va.vt = VT_BSTR;
pvaIn = &va;
uCmdID = IDM_BLOCKFMT;
}
if(0 != uCmdID && m_pCmdTarget)
{
hr = ExecCommand(uCmdID, dwOpt, pvaIn);
if(FAILED(hr))
goto error;
}
error:
if(va.vt == VT_BSTR && va.bstrVal != NULL)
SysFreeString(va.bstrVal);
return hr;
}
HRESULT CFmtBar::ExecCommand(UINT uCmdID, DWORD dwOpt, VARIANTARG *pvaIn)
{
HRESULT hr = S_FALSE;
if(uCmdID && m_pCmdTarget)
hr = m_pCmdTarget->Exec(&CMDSETID_Forms3,
uCmdID,
dwOpt,
pvaIn, NULL);
return hr;
}
HRESULT CFmtBar::SetCommandTarget(LPOLECOMMANDTARGET pCmdTarget)
{
// ALERT: we don't refcount these to avoid circular counts
// as this poitner is valid during the lifetime of the formatbar
m_pCmdTarget=pCmdTarget;
return NOERROR;
}
HRESULT HrCreateFormatBar(HWND hwndParent, int iddlg, BOOL fSep, LPFORMATBAR *ppFmtBar)
{
LPFORMATBAR pFmtBar=0;
HRESULT hr;
if(!ppFmtBar)
return E_INVALIDARG;
*ppFmtBar=NULL;
if(!(pFmtBar=new CFmtBar(fSep)))
return E_OUTOFMEMORY;
hr=pFmtBar->Init(hwndParent, iddlg);
if(FAILED(hr))
goto error;
*ppFmtBar=pFmtBar;
pFmtBar->AddRef();
error:
ReleaseObj(pFmtBar);
return hr;
}
void CFmtBar::WMNotify(WPARAM wParam, NMHDR* pnmhdr)
{
LPNMREBARCHEVRON pnmch;
if (pnmhdr->idFrom == idcCoolbar)
{
switch (pnmhdr->code)
{
case RBN_CHEVRONPUSHED:
{
ITrackShellMenu* ptsm;
CoCreateInstance(CLSID_TrackShellMenu, NULL, CLSCTX_INPROC_SERVER, IID_ITrackShellMenu,
(LPVOID*)&ptsm);
if (!ptsm)
break;
ptsm->Initialize(0, 0, 0, SMINIT_TOPLEVEL|SMINIT_VERTICAL);
LPNMREBARCHEVRON pnmch = (LPNMREBARCHEVRON) pnmhdr;
ptsm->SetObscured(m_hwndToolbar, NULL, SMSET_TOP);
MapWindowPoints(m_hwndRebar, HWND_DESKTOP, (LPPOINT)&pnmch->rc, 2);
POINTL pt = {pnmch->rc.left, pnmch->rc.right};
ptsm->Popup(m_hwndRebar, &pt, (RECTL*)&pnmch->rc, MPPF_BOTTOM);
ptsm->Release();
break;
}
}
}
switch(pnmhdr->code)
{
case TBN_DROPDOWN:
{
RECT rc;
POINT pt;
LPTBNOTIFY pTBN = (LPTBNOTIFY) pnmhdr;
if(pTBN->iItem == idmFmtColor)
SendMessage(m_hwndToolbar, TB_GETITEMRECT, 5, (LPARAM) &rc);
else if(pTBN->iItem == idmFmtTag)
SendMessage(m_hwndToolbar, TB_GETITEMRECT, 1, (LPARAM) &rc);
MapWindowPoints(m_hwndToolbar, NULL, (LPPOINT)&rc, 2);
pt.x=(GetWindowLong(m_hwndToolbar, GWL_EXSTYLE) & WS_EX_LAYOUTRTL) ?rc.right : rc.left;
pt.y=rc.bottom+2;
if(pTBN->iItem == idmFmtColor)
{
CheckColor();
ColorMenu_Show(m_hmenuColor, m_hwnd, pt, NULL);
}
else
if(pTBN->iItem == idmFmtTag)
HrShowTagMenu(pt);
}
break;
case TTN_NEEDTEXT:
ProcessTooltips((LPTOOLTIPTEXTOE) pnmhdr);
break;
}
}
void CFmtBar::OnDrawItem(LPDRAWITEMSTRUCT pdis)
{
switch(pdis->CtlType)
{
case ODT_MENU:
Color_WMDrawItem(m_hwnd, pdis);
break;
case ODT_COMBOBOX:
ComboBox_WMDrawItem(pdis);
break;
default:
AssertSz(0, "OwnerDraw type not supported");
}
}
void CFmtBar::OnMeasureItem(LPMEASUREITEMSTRUCT pmis)
{
HDC hdc;
HFONT hfontOld;
TEXTMETRIC tm;
hdc = GetDC(m_hwnd);
if(hdc)
{
switch(pmis->CtlType)
{
case ODT_MENU:
Color_WMMeasureItem(m_hwnd, hdc, pmis);
break;
case ODT_COMBOBOX:
hfontOld = (HFONT)SelectObject(hdc, (HFONT)SendMessage(m_hwndToolbar, WM_GETFONT, 0, 0));
GetTextMetrics(hdc, &tm);
SelectObject(hdc, hfontOld);
pmis->itemHeight = tm.tmHeight;
break;
default:
AssertSz(0, "OwnerDraw type not supported");
}
ReleaseDC(m_hwnd, hdc);
}
}
void Color_WMMeasureItem(HWND hwnd, HDC hdc, LPMEASUREITEMSTRUCT pmis)
{
HFONT hfontOld;
TEXTMETRIC tm;
UINT id = pmis->itemID;
TCHAR szColor[MAX_PATH]={0};
Assert (pmis->CtlType == ODT_MENU);
hfontOld = (HFONT)SelectObject(hdc, hFontGetMenuFont(hwnd));
GetTextMetrics(hdc, &tm);
SelectObject(hdc, hfontOld);
ULONG index = GETINDEX(pmis->itemData);
LoadString(g_hLocRes, index + idsColor1,
szColor, sizeof(szColor)/sizeof(TCHAR));
pmis->itemHeight = tm.tmHeight;
pmis->itemWidth = GetSystemMetrics(SM_CXMENUCHECK) +
2 * GetSystemMetrics(SM_CXBORDER) +
2 * tm.tmHeight +
(lstrlen(szColor) + 2) *tm.tmAveCharWidth;
}
// fill font name combo box
void CFmtBar::FillFontNames()
{
LOGFONT lf = {0};
HDC hdc;
// reset the contents of the combo
SendMessage(m_hwndName, CB_RESETCONTENT, 0, 0);
hdc = GetDC(NULL);
if (hdc)
{
//to enumerate all styles of all fonts for the default character set
lf.lfFaceName[0] = '\0';
lf.lfCharSet = DEFAULT_CHARSET;
EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC)ExtEnumFontNamesProcEx, (LPARAM)this, 0);
ReleaseDC(NULL, hdc);
}
}
LRESULT CALLBACK CFmtBar::EditSubProc(HWND hwnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
CHAR szBuf[TEMPBUFSIZE];
HWND hwndCombo = GetParent(hwnd);
LPFORMATBAR pFmtBar = NULL;
if(hwndCombo == NULL)
{
AssertSz(0, "This is bad");
return 0;
}
pFmtBar = (LPFORMATBAR)GetProp(hwnd, c_szThis);
if(pFmtBar == NULL)
{
AssertSz(0, "This is bad");
return 0;
}
*szBuf = 0;
switch (wMsg)
{
case WM_KEYDOWN:
switch(wParam)
{
case VK_ESCAPE:
pFmtBar->SetBodyFocus();
return 0;
case VK_RETURN:
if (!SendMessage(pFmtBar->m_hwndName, CB_GETDROPPEDSTATE, 0, 0))
{
ComboBox_GetText(hwnd, szBuf, sizeof(szBuf));
ComboBox_SelectString(pFmtBar->m_hwndName, -1, szBuf);
SendMessage(pFmtBar->m_hwnd, WM_COMMAND, (WPARAM)MAKELONG(idmFmtFont, CBN_SELENDOK), (LPARAM)pFmtBar->m_hwndName);
return 0;
}
}
break;
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_MOUSEMOVE:
{
MSG msg;
msg.lParam = lParam;
msg.wParam = wParam;
msg.message = wMsg;
msg.hwnd = hwnd;
SendMessage((HWND)SendMessage(pFmtBar->m_hwndToolbar, TB_GETTOOLTIPS, 0, 0), TTM_RELAYEVENT, 0, (LPARAM) &msg);
}
break;
}
return CallWindowProc(pFmtBar->m_wndprocEdit, hwnd, wMsg, wParam, lParam);
}
LRESULT CALLBACK CFmtBar::ComboBoxSubProc(HWND hwnd, UINT wMsg, WPARAM wParam,
LPARAM lParam)
{
INT nID = GetWindowID(hwnd);
WNDPROC wndprocNext;
LPFORMATBAR pFmtBar = NULL;
pFmtBar = (LPFORMATBAR)GetProp(hwnd, c_szThis);
if(pFmtBar == NULL)
{
AssertSz(0, "This is bad");
return 0;
}
switch (wMsg)
{
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_MOUSEMOVE:
{
MSG msg;
msg.lParam = lParam;
msg.wParam = wParam;
msg.message = wMsg;
msg.hwnd = hwnd;
SendMessage((HWND)SendMessage(pFmtBar->m_hwndToolbar, TB_GETTOOLTIPS, 0, 0), TTM_RELAYEVENT, 0, (LPARAM) &msg);
}
break;
}
if (nID == idmFmtFont)
wndprocNext = pFmtBar->m_wndprocNameComboBox;
else
wndprocNext = pFmtBar->m_wndprocSizeComboBox;
return wndprocNext ? CallWindowProc(wndprocNext, hwnd, wMsg, wParam, lParam) : 0;
}
INT CALLBACK CFmtBar::ExtEnumFontNamesProcEx(ENUMLOGFONTEX *plf, NEWTEXTMETRICEX *ptm, INT nFontType, LPARAM lParam)
{
return ((CFmtBar *)lParam)->EnumFontNamesProcEx(plf, ptm, nFontType);
}
INT CFmtBar::EnumFontNamesProcEx(ENUMLOGFONTEX *plf, NEWTEXTMETRICEX *ptm, INT nFontType)
{
CFmtBar *pFmtBar;
LONG l;
// skip vertical fonts for OE
if (plf->elfLogFont.lfFaceName[0]=='@')
return TRUE;
// if the font is already listed, don't re-list it
if(ComboBox_FindStringExact(m_hwndName, -1, plf->elfLogFont.lfFaceName) != -1)
return TRUE;
l = ComboBox_AddString(m_hwndName, plf->elfLogFont.lfFaceName);
if (l!=-1)
ComboBox_SetItemData(m_hwndName, l, nFontType);
return TRUE;
}
INT CFmtBar::XFontSizeCombo(HDC hdc)
{
LONG id;
TCHAR szBuf[TEMPBUFSIZE];
*szBuf = 0;
INT iMax=0;
SIZE rSize;
for(id = idsFontSize0; id < NFONTSIZES + idsFontSize0; ++id)
{
LoadString(g_hLocRes, id, szBuf, sizeof(szBuf));
GetTextExtentPoint32 (hdc, szBuf, lstrlen(szBuf), &rSize);
if(rSize.cx > iMax)
iMax = rSize.cx;
}
return iMax + 10;
}
void CFmtBar::FillSizes()
{
LONG id;
TCHAR szBuf[TEMPBUFSIZE];
*szBuf = 0;
LRESULT lr;
// Empty the current list
SendMessage(m_hwndSize, CB_RESETCONTENT, 0, 0);
for (id = idsFontSize0; id < NFONTSIZES + idsFontSize0; ++id)
{
LoadString(g_hLocRes, id, szBuf, sizeof(szBuf));
lr = SendMessage(m_hwndSize, CB_ADDSTRING, 0, (LPARAM) szBuf);
if (lr == CB_ERR || lr == CB_ERRSPACE)
break;
}
}
#define BACKGROUND 0x000000FF // bright blue
#define BACKGROUNDSEL 0x00FF00FF // bright blue
DWORD CFmtBar::FlipColor(DWORD rgb)
{
return RGB(GetBValue(rgb), GetGValue(rgb), GetRValue(rgb));
}
// load bitmap for true type font
HBITMAP CFmtBar::LoadDIBBitmap(int id)
{
HDC hdc;
HRSRC h;
DWORD FAR * p;
LPSTR lpBits;
HANDLE hRes;
LPBITMAPINFOHEADER lpBitmapInfo;
LPVOID lpRes;
DWORD cbRes;
int numcolors;
DWORD rgbSelected;
DWORD rgbUnselected;
HBITMAP hbm;
rgbSelected = FlipColor(GetSysColor(COLOR_HIGHLIGHT));
rgbUnselected = FlipColor(GetSysColor(COLOR_WINDOW));
h = FindResource(g_hLocRes, MAKEINTRESOURCE(id), RT_BITMAP);
hRes = LoadResource(g_hLocRes, h);
/* Lock the bitmap and get a pointer to the color table. */
lpRes = LockResource(hRes);
if (!lpRes)
return NULL;
/* Copy the resource since we shouldn't modify the original */
cbRes = SizeofResource(g_hLocRes, h);
if(!MemAlloc((LPVOID *)&lpBitmapInfo, LOWORD(cbRes)))
return NULL;
CopyMemory(lpBitmapInfo, lpRes, cbRes);
p = (DWORD FAR *)((LPSTR)(lpBitmapInfo) + lpBitmapInfo->biSize);
/* Search for the Solid Blue entry and replace it with the current
* background RGB.
*/
numcolors = 16;
while (numcolors-- > 0)
{
if (*p == BACKGROUND)
*p = rgbUnselected;
else if (*p == BACKGROUNDSEL)
*p = rgbSelected;
p++;
}
/* First skip over the header structure */
lpBits = (LPSTR)(lpBitmapInfo + 1);
/* Skip the color table entries, if any */
lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
/* Create a color bitmap compatible with the display device */
hdc = GetDC(NULL);
hbm = CreateDIBitmap(hdc, lpBitmapInfo, (DWORD)CBM_INIT, lpBits,
(LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS);
ReleaseDC(NULL, hdc);
SafeMemFree(lpBitmapInfo);
FreeResource(hRes);
return hbm;
}
VOID CFmtBar::AddToolTip(HWND hwndToolTips, HWND hwnd, UINT idRsrc)
{
TOOLINFO ti = { 0 };
ti.cbSize = sizeof(TOOLINFO);
ti.uFlags = TTF_IDISHWND;
ti.hwnd = hwnd;
ti.uId = (UINT_PTR) hwnd;
GetWindowRect(hwnd, &ti.rect);
ti.hinst = g_hLocRes;
ti.lpszText = (LPSTR) IntToPtr(idRsrc);
SendMessage(hwndToolTips, TTM_ADDTOOL, 0, (LPARAM) &ti);
}
HRESULT CFmtBar::TranslateAcclerator(LPMSG lpMsg)
{
HWND hwndFocus;
if (m_hwnd &&
lpMsg->message==WM_KEYDOWN &&
((lpMsg->wParam==VK_RETURN || lpMsg->wParam==VK_ESCAPE)))
{
hwndFocus=GetFocus();
// if focus is on the size combolist or in the edit of the
// name combobox, then we translate the messages to the window.
if(hwndFocus==::GetWindow(m_hwndName, GW_CHILD) ||
hwndFocus==m_hwndSize)
{
TranslateMessage(lpMsg);
DispatchMessage(lpMsg);
return S_OK;
}
}
return S_FALSE;
}
BOOL CFmtBar::FBodyHasFocus()
{
NMHDR nmhdr;
nmhdr.hwndFrom=m_hwnd;
nmhdr.idFrom=GetDlgCtrlID(m_hwnd);
nmhdr.code=FBN_BODYHASFOCUS;
return (0 != SendMessage(GetParent(m_hwnd), WM_NOTIFY, nmhdr.idFrom, (LPARAM)&nmhdr));
}
void CFmtBar::SetBodyFocus()
{
NMHDR nmhdr;
nmhdr.hwndFrom=m_hwnd;
nmhdr.idFrom=GetDlgCtrlID(m_hwnd);
nmhdr.code=FBN_BODYSETFOCUS;
SendMessage(GetParent(m_hwnd), WM_NOTIFY, nmhdr.idFrom, (LPARAM)&nmhdr);
}
void CFmtBar::ComboBox_WMDrawItem(LPDRAWITEMSTRUCT pdis)
{
HDC hdc,
hdcMem;
DWORD rgbBack, rgbText;
char szFace[LF_FACESIZE + 10];
HBITMAP hbmOld;
int dy,
x;
INT nFontType = (INT) pdis->itemData;
SIZE size;
TOOLINFO ti;
RECT rc;
Assert(pdis->CtlID == idmFmtFont);
hdc = pdis->hDC;
if (pdis->itemState & ODS_SELECTED)
{
rgbBack = SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
rgbText = SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
}
else
{
rgbBack = SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
rgbText = SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
}
SendMessage(pdis->hwndItem, CB_GETLBTEXT, pdis->itemID,
(LPARAM)(LPSTR)szFace);
ExtTextOut(hdc, pdis->rcItem.left + dxFormatFontBitmap,
pdis->rcItem.top, ETO_OPAQUE, &pdis->rcItem,
szFace, lstrlen(szFace), NULL);
// if selected, see if it is clipped, so that we know to show a tooltip
if ((pdis->itemState & ODS_SELECTED) &&
GetTextExtentPoint32(hdc, szFace, lstrlen(szFace), &size) &&
size.cx + dxFormatFontBitmap >= pdis->rcItem.right)
{
ZeroMemory(&ti, sizeof(TOOLINFO));
ti.cbSize = sizeof(TOOLINFO);
ti.hwnd = m_hwndName;
ti.uId = (UINT_PTR)m_hwndName;
ti.lpszText = szFace;
SendMessage(m_hwndName, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)&rc);
SendMessage(m_hwndTT, TTM_UPDATETIPTEXT, 0, (LPARAM)&ti);
SendMessage(m_hwndTT, TTM_TRACKPOSITION, 0, MAKELPARAM(rc.left + pdis->rcItem.left + dxFormatFontBitmap,
rc.top + pdis->rcItem.top));
SendMessage(m_hwndTT, TTM_TRACKACTIVATE, TRUE, (LPARAM) &ti);
}
else
SendMessage(m_hwndTT, TTM_TRACKACTIVATE, FALSE, (LPARAM) &ti);
hdcMem = CreateCompatibleDC(hdc);
if (hdcMem)
{
if (m_hbmName)
{
hbmOld = (HBITMAP)SelectObject(hdcMem, m_hbmName);
x = dxFormatFontBitmap;
if (nFontType & TRUETYPE_FONTTYPE)
x = 0;
else if ((nFontType & (PRINTER_FONTTYPE | DEVICE_FONTTYPE)) ==
(PRINTER_FONTTYPE | DEVICE_FONTTYPE))
x = dxFormatFontBitmap;
else
goto SkipBlt;
dy = ((pdis->rcItem.bottom - pdis->rcItem.top) -
dyFormatFontBitmap) / 2;
BitBlt(hdc, pdis->rcItem.left, pdis->rcItem.top + dy,
dxFormatFontBitmap, dyFormatFontBitmap, hdcMem,
x, pdis->itemState & ODS_SELECTED ? dyFormatFontBitmap: 0,
SRCCOPY);
SkipBlt:
SelectObject(hdcMem, hbmOld);
}
DeleteDC(hdcMem);
}
SetTextColor(hdc, rgbText);
SetBkColor(hdc, rgbBack);
}
void Color_WMDrawItem(HWND hwnd, LPDRAWITEMSTRUCT pdis)
{
HBRUSH hbr;
WORD dx, dy, dxBorder;
RECT rc;
TCHAR szColor[MAX_PATH]={0};
DWORD rgbBack, rgbText;
UINT id = pdis->itemID;
ULONG index = 0;
Assert (pdis->CtlType == ODT_MENU);
if(pdis->itemState&ODS_SELECTED)
{
rgbBack = SetBkColor(pdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
rgbText = SetTextColor(pdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
}
else
{
rgbBack = SetBkColor(pdis->hDC, GetSysColor(COLOR_MENU));
rgbText = SetTextColor(pdis->hDC, GetSysColor(COLOR_MENUTEXT));
}
// compute coordinates of color rectangle and draw it
dxBorder = (WORD) GetSystemMetrics(SM_CXBORDER);
dx = (WORD) GetSystemMetrics(SM_CXMENUCHECK);
dy = (WORD) GetSystemMetrics(SM_CYBORDER);
rc.top = pdis->rcItem.top + dy;
rc.bottom = pdis->rcItem.bottom - dy;
rc.left = pdis->rcItem.left + dx;
rc.right = rc.left + 2 * (rc.bottom - rc.top);
index = GETINDEX(pdis->itemData);
LoadString(g_hLocRes, index + idsColor1,
szColor, sizeof(szColor)/sizeof(TCHAR));
SelectObject(pdis->hDC, hFontGetMenuFont(hwnd));
ExtTextOut(pdis->hDC, rc.right + 2*dxBorder,
pdis->rcItem.top, ETO_OPAQUE, &pdis->rcItem,
szColor, lstrlen(szColor), NULL);
hbr = CreateSolidBrush((DWORD)(pdis->itemData & 0x00ffffff));
if (hbr)
{
hbr = (HBRUSH)SelectObject (pdis->hDC, hbr);
Rectangle(pdis->hDC, rc.left, rc.top, rc.right, rc.bottom);
DeleteObject(SelectObject(pdis->hDC, hbr));
}
// draw radio check.
if (pdis->itemState&ODS_CHECKED)
{
WORD left, top, radius;
if(pdis->itemState&ODS_SELECTED)
hbr = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHTTEXT));
else
hbr = CreateSolidBrush(GetSysColor(COLOR_MENUTEXT));
if (hbr)
{
hbr = (HBRUSH)SelectObject (pdis->hDC, hbr);
#ifndef WIN16
left = (WORD) (pdis->rcItem.left + GetSystemMetrics(SM_CXMENUCHECK) / 2);
#else
left = pdis->rcItem.left + LOWORD( GetMenuCheckMarkDimensions() ) / 2;
#endif
top = (WORD) (rc.top + (rc.bottom - rc.top) / 2);
#ifndef WIN16
radius = (WORD) (GetSystemMetrics(SM_CXMENUCHECK) / 4);
#else
radius = LOWORD( GetMenuCheckMarkDimensions() ) / 4;
#endif
Ellipse(pdis->hDC, left-radius, top-radius, left+radius, top+radius);
DeleteObject(SelectObject(pdis->hDC, hbr));
}
}
SetTextColor(pdis->hDC, rgbText);
SetBkColor(pdis->hDC, rgbBack);
}
HRESULT CFmtBar::Show()
{
HRESULT hr;
if (m_fVisible)
return S_OK;
hr = AttachWin();
if (FAILED(hr))
return hr;
ShowWindow(m_hwnd, SW_SHOW);
m_fVisible=1;
Update();
return S_OK;
}
HRESULT CFmtBar::Hide()
{
if (!m_fVisible)
return S_OK;
ShowWindow(m_hwnd, SW_HIDE);
m_fVisible=0;
return S_OK;
}
HRESULT CFmtBar::GetWindow(HWND *pHwnd)
{
*pHwnd = m_hwnd;
return S_OK;
}
HRESULT CFmtBar::AttachWin()
{
HWND hwnd;
WNDCLASS wc;
if (m_hwnd) // already created
return S_OK;
if (FAILED(CreateColorMenu(idmFmtColor1, &m_hmenuColor)))
return E_FAIL;
if (!GetClassInfo(g_hLocRes, c_szFmtBarClass, &wc))
{
ZeroMemory(&wc, sizeof(WNDCLASS));
wc.style = CS_BYTEALIGNWINDOW;
wc.lpfnWndProc = CFmtBar::ExtWndProc;
wc.hInstance = g_hLocRes;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wc.lpszClassName = c_szFmtBarClass;
if (!RegisterClass(&wc))
return E_FAIL;
}
hwnd = CreateWindowEx(WS_EX_CONTROLPARENT,
c_szFmtBarClass, NULL,
WS_CHILD|WS_CLIPCHILDREN,
0, 0, 0, 0,
m_hwndParent, (HMENU)IntToPtr(m_idd), g_hLocRes, (LPVOID)this);
if(!hwnd)
return E_OUTOFMEMORY;
return S_OK;
}
HFONT hFontGetMenuFont(HWND hwnd)
{
NMHDR nmhdr;
nmhdr.hwndFrom=hwnd;
nmhdr.idFrom=GetDlgCtrlID(hwnd);
nmhdr.code=FBN_GETMENUFONT;
return (HFONT)SendMessage(GetParent(hwnd), WM_NOTIFY, nmhdr.idFrom, (LPARAM)&nmhdr);
}
HRESULT CFmtBar::_SetToolbarBitmaps()
{
// release toolbar references
SendMessage(m_hwndToolbar, TB_SETIMAGELIST, 0, (LPARAM)NULL);
SendMessage(m_hwndToolbar, TB_SETHOTIMAGELIST, 0, (LPARAM)NULL);
_FreeImageLists();
// set the normal imagelist
m_himl = LoadMappedToolbarBitmap(g_hLocRes, idbFormatBar, dxToolbarButton);
if (!m_himl)
return E_OUTOFMEMORY;
SendMessage(m_hwndToolbar, TB_SETIMAGELIST, 0, (LPARAM)m_himl);
// the the HOT imagelist
m_himlHot = LoadMappedToolbarBitmap(g_hLocRes, idbFormatBarHot, dxToolbarButton);
if (!m_himlHot)
return E_OUTOFMEMORY;
SendMessage(m_hwndToolbar, TB_SETHOTIMAGELIST, 0, (LPARAM)m_himlHot);
return S_OK;
}
HRESULT CFmtBar::_FreeImageLists()
{
if (m_himlHot)
{
ImageList_Destroy(m_himlHot);
m_himlHot = NULL;
}
if (m_himl)
{
ImageList_Destroy(m_himl);
m_himl = NULL;
}
return S_OK;
}