⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 frmtbar.c

📁 文本编辑器
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 *		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 + -