📄 frmtbar.c
字号:
/*
* frmtbar.c
*
* Implementation of a richedit format bar
*
*/
#include "preinc.h"
#include <windows.h>
#include <windowsx.h>
#include <richedit.h>
#include <commctrl.h>
#include "dbugit.h"
#include "reitp.rh"
#include "frmtbar.h"
ASSERTDATA
/*
* The current format state
*/
typedef struct tagFormatBarState
{
HWND hwndToolbar; // Toolbar
HWND hwndName; // Font name combo
HWND hwndSize; // Font size combo
HWND hwndColor; // Font color combo
HDC hdc; // Our copy of the DC to use
INT cyPerInch; // Pixels per inch vertically
HBRUSH hbrushWindow; // Common brushes
HBRUSH hbrushHighlight;
HBRUSH hbrushButtonFace;
COLORREF crWindow; // Common colors
COLORREF crHighlight;
COLORREF crButtonFace;
CHARFORMAT cf; // The current char format
PARAFORMAT pf; // The current paragraph format
DWORD dwCFMaskChange; // What changed
LONG rglSize[128]; // Possible font sizes
LONG clSize; // Number of font sizes
BOOL fTrueType; // TrueType flag
BOOL fExpectChoice; // Flag that we want next CBN_*
BOOL fGiveUpFocus; // Flag that we are done
} FormatBarState;
#define PfbsGetWindowPtr(_hwnd) \
((FormatBarState *) GetWindowLong(_hwnd, 0))
#define SetWindowPtr(_hwnd, _p) SetWindowLong(_hwnd, 0, (LONG) _p)
#define GetFormatBarField(_hwnd, _fld) (PfbsGetWindowPtr(_hwnd)->_fld)
/*
* Range of sizes we'll show user for TrueType fonts
*/
#define lTrueTypeSizeMin 4
#define lTrueTypeSizeMac 127
static TCHAR szFormatBar[] = FORMATBARCLASSNAME;
static TCHAR szToolbar[] = TOOLBARCLASSNAME;
static TCHAR szComboBox[] = "ComboBox";
/*
* Our own private messages from the combobox edit control to the format bar
* letting up know about important keyevents
* wParam = window ID of the combobox owning the edit control
* lParam = window handle of the combobox owning the edit control
* returns: none
*/
#define WM_TAB ( WM_USER + 1 )
#define WM_RETURN ( WM_USER + 2 )
#define WM_ESCAPE ( WM_USER + 3 )
#define cxDownButton 16
#define cxName 128 + cxDownButton
#define cxSize 40 + cxDownButton
#define cxColor 24 + cxDownButton
#define cxGap1 (8 + cxName + 8 + cxSize + 8)
#define cxGap2 (cxColor + 8)
#define CFM_MASKS ( CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE | CFM_COLOR )
#define CFE_EFFECTS ( CFE_BOLD | CFE_ITALIC | CFE_UNDERLINE | \
CFE_AUTOCOLOR )
#define INITIAL_COLOR 0x40000000
static TBBUTTON rgtbbutton[] =
{
{ cxGap1, 0L, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0, 0L, -1},
{ tbBold, TBI_Bold, TBSTATE_ENABLED, TBSTYLE_CHECK, 0, 0, 0L, -1},
{ tbItalic, TBI_Italic, TBSTATE_ENABLED, TBSTYLE_CHECK, 0, 0, 0L, -1},
{ tbUnderline, TBI_Underline, TBSTATE_ENABLED, TBSTYLE_CHECK, 0, 0, 0L, -1},
{ cxGap2, 0L, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0, 0L, -1},
{ tbBullet, TBI_Bullet, TBSTATE_ENABLED, TBSTYLE_CHECK, 0, 0, 0L, -1},
{ 0, 0L, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0, 0L, -1},
{ tbDecreaseIndent, TBI_DecreaseIndent, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0L, -1},
{ tbIncreaseIndent, TBI_IncreaseIndent, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0L, -1},
{ 0, 0L, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0, 0L, -1},
{ tbLeft, TBI_Left, TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, 0, 0, 0L, -1},
{ tbCenter, TBI_Center, TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, 0, 0, 0L, -1},
{ tbRight, TBI_Right, TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, 0, 0, 0L, -1},
{ 0, 0L, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0, 0L, -1},
};
#define ctbbutton (sizeof(rgtbbutton) / sizeof(TBBUTTON))
static DWORD rgdwCFEffect[] = { CFE_BOLD, CFE_ITALIC, CFE_UNDERLINE };
static WORD rgwPFAlignment[] = { PFA_LEFT, PFA_CENTER, PFA_RIGHT };
// Hold the old wndproc's !
//$ REVIEW: Make this per instance ?
static WNDPROC pfnEditWndProc = NULL;
static WNDPROC pfnComboBoxWndProc = NULL;
static WNDPROC pfnToolbarWndProc = NULL;
/*
* Color table for dropdown on toolbar. Matches COMMDLG colors
* exactly.
*/
static DWORD rgrgbColors[] = {
RGB( 0, 0, 0), /* Black */
RGB(128, 0, 0), /* Dark red */
RGB( 0, 128, 0), /* Dark green */
RGB(128, 128, 0), /* Dark yellow */
RGB( 0, 0, 128), /* Dark blue */
RGB(128, 0, 128), /* Dark purple */
RGB( 0, 128, 128), /* Dark aqua */
RGB(128, 128, 128), /* Dark grey */
RGB(192, 192, 192), /* Light grey */
RGB(255, 0, 0), /* Light red */
RGB( 0, 255, 0), /* Light green */
RGB(255, 255, 0), /* Light yellow */
RGB( 0, 0, 255), /* Light blue */
RGB(255, 0, 255), /* Light purple */
RGB( 0, 255, 255), /* Light aqua */
RGB(255, 255, 255), /* White */
};
const INT crgbColorsMax = sizeof(rgrgbColors) / sizeof(rgrgbColors[0]);
#define TraceCharFormat(_sz, _pcf)
/*
* UpdateBrush
*
* Purpose:
* Syncs up the brushes with the known color scheme as needed
*
* Arguments:
* hwnd Handle of the format bar
*
* Returns:
* None.
*/
LOCAL VOID UpdateBrush(HBRUSH * phbrush, COLORREF * pcr, INT nIndex)
{
COLORREF cr;
if (((cr = GetSysColor(nIndex)) != *pcr) ||
!*phbrush)
{
if (*phbrush)
DeleteObject(*phbrush);
*phbrush = CreateSolidBrush(*pcr = cr);
}
}
/*
* UpdateBrushes
*
* Purpose:
* Syncs up the brushes with the known color scheme as needed
*
* Arguments:
* hwnd Handle of the format bar
*
* Returns:
* None.
*/
LOCAL VOID UpdateBrushes(HWND hwnd)
{
FormatBarState * pfbs = PfbsGetWindowPtr(hwnd);
UpdateBrush(&pfbs->hbrushWindow, &pfbs->crWindow, COLOR_WINDOW);
UpdateBrush(&pfbs->hbrushHighlight, &pfbs->crHighlight, COLOR_HIGHLIGHT);
UpdateBrush(&pfbs->hbrushButtonFace, &pfbs->crButtonFace, COLOR_BTNFACE);
}
/*
* LFBEditWndProc
*
* Purpose:
* Take care of handling the notifications from the combobox controls we
* get for the format bar
*
* Arguments:
* hwnd
* wMsg
* wParam
* lParam
*
* Returns:
* LRESULT
*/
LRESULT CALLBACK LFBEditWndProc(HWND hwnd, UINT wMsg, WPARAM wParam,
LPARAM lParam)
{
switch (wMsg)
{
case WM_KEYDOWN:
{
HWND hwndCombo = GetParent(hwnd);
HWND hwndFormatBar = GetParent(GetParent(hwndCombo));
INT nID = GetWindowID(hwndCombo);
switch(wParam)
{
case VK_ESCAPE:
SendMessage(hwndFormatBar, WM_ESCAPE, nID,
(LPARAM) (LPTSTR) hwndCombo);
case VK_TAB:
case VK_RETURN:
return 0;
}
}
break;
case WM_CHAR:
{
HWND hwndCombo = GetParent(hwnd);
HWND hwndFormatBar = GetParent(GetParent(hwndCombo));
INT nID = GetWindowID(hwndCombo);
switch(wParam)
{
case VK_RETURN:
SendMessage(hwndFormatBar, WM_RETURN, nID,
(LPARAM) (LPTSTR) hwndCombo);
return 0;
case VK_TAB:
SendMessage(hwndFormatBar, WM_TAB, nID,
(LPARAM) (LPTSTR) hwndCombo);
return 0;
case VK_ESCAPE:
return 0;
}
}
break;
case WM_KEYUP:
switch (wParam)
{
case VK_RETURN:
case VK_TAB:
case VK_ESCAPE:
return 0;
}
break;
}
return CallWindowProc(pfnEditWndProc, hwnd, wMsg, wParam, lParam);
}
/*
* LFBComboBoxWndProc
*
* Purpose:
* Take care of handling the notifications from the combobox controls we
* get for the format bar
*
* Arguments:
* hwnd
* wMsg
* wParam
* lParam
*
* Returns:
* LRESULT
*/
LRESULT CALLBACK LFBComboBoxWndProc(HWND hwnd, UINT wMsg, WPARAM wParam,
LPARAM lParam)
{
switch (wMsg)
{
case WM_KEYDOWN:
{
HWND hwndFormatBar = GetParent(GetParent(hwnd));
INT nID = GetWindowID(hwnd);
switch(wParam)
{
case VK_TAB:
SendMessage(hwndFormatBar, WM_TAB, nID,
(LPARAM) (LPTSTR) hwnd);
return 0;
case VK_RETURN:
SendMessage(hwndFormatBar, WM_RETURN, nID,
(LPARAM) (LPTSTR) hwnd);
return 0;
case VK_ESCAPE:
SendMessage(hwndFormatBar, WM_ESCAPE, nID,
(LPARAM) (LPTSTR) hwnd);
return 0;
}
}
break;
case WM_KEYUP:
case WM_CHAR:
switch(wParam)
{
case VK_TAB:
case VK_RETURN:
case VK_ESCAPE:
return 0;
}
break;
}
return CallWindowProc(pfnComboBoxWndProc, hwnd, wMsg, wParam, lParam);
}
/*
* LFBToolbarWndProc
*
* Purpose:
* Take care of handling the notifications from the combobox controls we
* get for the format bar
*
* Arguments:
* hwnd
* wMsg
* wParam
* lParam
*
* Returns:
* LRESULT
*/
LRESULT CALLBACK LFBToolbarWndProc(HWND hwnd, UINT wMsg, WPARAM wParam,
LPARAM lParam)
{
switch (wMsg)
{
case WM_CTLCOLORLISTBOX:
{
FormatBarState * pfbs = PfbsGetWindowPtr(GetParent(hwnd));
// Peek at the current information
UpdateBrush(&pfbs->hbrushButtonFace, &pfbs->crButtonFace,
COLOR_BTNFACE);
return (LRESULT) (LPTSTR) pfbs->hbrushButtonFace;
}
break;
}
return CallWindowProc(pfnToolbarWndProc, hwnd, wMsg, wParam, lParam);
}
/*
* NEnumFontNameProc
*
* Purpose:
* The callback for EnumFontFamilies which fills the font names combobox
* with the available fonts
*
* Arguments:
*
* Returns:
* Non-zero as long a font name can be inserted into the combobox
*/
INT CALLBACK NEnumFontNameProc(LOGFONT * plf, TEXTMETRIC * ptm,
INT nFontType, LPARAM lParam)
{
LRESULT lr;
DWORD dw;
lr = SendMessage((HWND) lParam, CB_ADDSTRING, 0, (LPARAM) plf->lfFaceName);
if (!(lr == CB_ERR || lr == CB_ERRSPACE))
{
Assert (!(plf->lfCharSet & 0xFFFFFF00));
Assert (!(plf->lfPitchAndFamily & 0xFFFFFF00));
Assert (!(nFontType & 0xFFFF0000));
dw = plf->lfCharSet & 0xFF;
dw <<= 8;
dw |= plf->lfPitchAndFamily & 0xFF;
dw <<= 16;
dw |= nFontType & 0xFFFF;
SendMessage((HWND) lParam, CB_SETITEMDATA, LOWORD(lr), (LPARAM) dw);
}
return !(lr == CB_ERR || lr == CB_ERRSPACE);
}
/*
* FillNames
*
* Purpose:
* Fills the font name combobox with the names of the available fonts
*
* Arguments:
* hwnd Handle of the names combobox
*
* Returns:
* None.
*/
LOCAL void FillNames(HWND hwnd)
{
FormatBarState * pfbs = PfbsGetWindowPtr(hwnd);
HDC hdc = pfbs->hdc;
HWND hwndName = pfbs->hwndName;
// Empty the current list
SendMessage(hwndName, CB_RESETCONTENT, 0, 0);
// Ask for all the font families
EnumFontFamilies((HDC) hdc, (LPTSTR) NULL,
(FONTENUMPROC) NEnumFontNameProc,
(LPARAM) (LPTSTR) hwndName);
}
/*
* FInsertSize
*
* Purpose:
* Inserts a font size entry into the array. Takes care of the necessary
* conversion from logical units to points size. The array is kept in
* ascending order.
*
* Arguments:
* lSize The font size in logical units
* pfbs The current format bar state
* fPoints Flag whether the size is in points or not
*
* Returns:
* TRUE if the font size was successfully added to the array, or was
* present.
*/
BOOL FInsertSize(LONG lSize, FormatBarState * pfbs, BOOL fPoints)
{
LONG clLeft = pfbs->clSize;
LONG * plSize = pfbs->rglSize;
if (clLeft >= sizeof(pfbs->rglSize) / sizeof(LONG))
return FALSE;
// Convert to point sizes
if (!fPoints)
lSize = MulDiv((INT) lSize, 72, pfbs->cyPerInch);
while (clLeft > 0 && *plSize < lSize)
{
++plSize;
--clLeft;
}
if (clLeft && *plSize == lSize)
;
else
{
if (clLeft)
{
MoveMemory(plSize + 1, plSize, clLeft * sizeof(LONG));
}
*plSize = lSize;
++pfbs->clSize;
}
return TRUE;
}
/*
* NEnumFontSizeProc
*
* Purpose:
* The callback for EnumFontFamilies which fills the font names combobox
* with the available fonts
*
* Arguments:
*
* Returns:
* Non-zero as long a font name can be inserted into the combobox
*/
INT CALLBACK NEnumFontSizeProc(LOGFONT * plf, TEXTMETRIC * ptm,
INT nFontType, LPARAM lParam)
{
FormatBarState * pfbs = (FormatBarState *) lParam;
if (ptm->tmPitchAndFamily & TMPF_TRUETYPE)
pfbs->fTrueType |= TRUE;
return FInsertSize(ptm->tmHeight - ptm->tmInternalLeading, pfbs, FALSE);
}
/*
* FFillSizes
*
* Purpose:
* Fills the font name combobox with the names of the available fonts
*
* Arguments:
* hwnd Handle of the names combobox
*
* Returns:
* TRUE if successful
*/
LOCAL BOOL FFillSizes(HWND hwnd)
{
FormatBarState * pfbs = PfbsGetWindowPtr(hwnd);
HDC hdc = pfbs->hdc;
HWND hwndSize = pfbs->hwndSize;
TCHAR * pszFaceName = pfbs->cf.szFaceName;
LONG ilSize;
LONG lCurrSize;
LONG ilMatch;
LONG * plSize = pfbs->rglSize;
TCHAR szT[10];
LRESULT lr;
BOOL fSuccess = FALSE;
// Empty the current list
SendMessage(hwndSize, CB_RESETCONTENT, 0, 0);
pfbs->clSize = 0;
pfbs->fTrueType = FALSE;
// Ask for all the font sizes for the given font
EnumFontFamilies((HDC) hdc, pszFaceName,
(FONTENUMPROC) NEnumFontSizeProc, (LPARAM) pfbs);
// If we got a TrueType font, just fill in the array with our sizes
if (pfbs->fTrueType)
{
ilSize = lTrueTypeSizeMin;
while (ilSize < lTrueTypeSizeMac)
*plSize++ = ilSize++;
*plSize = ilSize;
pfbs->clSize = lTrueTypeSizeMac - lTrueTypeSizeMin + 1;
}
// Save ourselves some dereferencing and covert to points
lCurrSize = MulDiv((INT) pfbs->cf.yHeight, 72, 1440);
// Now go through our entries and put them into our listbox
plSize = pfbs->rglSize;
ilMatch = -1;
for (ilSize = 0; ilSize < pfbs->clSize; ++ilSize, ++plSize)
{
wsprintf(szT, "%ld", *plSize);
lr = SendMessage(hwndSize, CB_ADDSTRING, 0, (LPARAM) szT);
AssertSz(!(lr == CB_ERR || lr == CB_ERRSPACE), "Can't add more sizes");
if (lr == CB_ERR || lr == CB_ERRSPACE)
goto CleanUp;
// Try to find out which element will become our current selection
if (*plSize == lCurrSize)
ilMatch = ilSize;
}
// Set our current selection
if (ilMatch >= 0)
SendMessage(hwndSize, CB_SETCURSEL, (WPARAM) ilMatch, 0);
else
{
if (lCurrSize)
wsprintf(szT, "%ld", lCurrSize);
else
szT[0] = 0;
SetWindowText(hwndSize, szT);
}
fSuccess = TRUE;
CleanUp:
return fSuccess;
}
/*
* FillColors
*
* Purpose:
* Fills the font colors combobox with samples of the available colors
*
* Arguments:
* hwnd Handle of the names combobox
*
* Returns:
* None.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -