rulerricheditctrl.cpp

来自「管理项目进度工具的原代码」· C++ 代码 · 共 2,215 行 · 第 1/4 页

CPP
2,215
字号
/* ==========================================================================
	File :			RuleRichEditCtrl.cpp

	Class :			CRulerRichEditCtrl

	Author :		Johan Rosengren, Abstrakt Mekanik AB
					Iain Clarke

	Date :			2004-04-17

	Purpose :		"CRulerRichEditCtrl" is a "CWnd" derived class containing an 
					embedded RTF-control, a ruler-control with dragable tab-
					positions and a formatting toolbar. The class can be used 
					to - for example - add a complete mini-editor to a modal 
					or modeless dialog box. 

	Description :	The class mainly handles mouse messages. The mouse
					messages are sent from the ruler control, and are 
					button down, where the a check is made for the cursor 
					located on one of the tab-markers, mouse move, where an 
					XORed line is drawn across the RTF-control and button up, 
					where a new tab position is set. The class also handles 
					the toolbar buttons, setting styles as 
					appropriate for the selected text.

	Usage :			Add a "CRulerRichEditCtrl"-member to the parent class. 
					Call Create to create the control. "GetRichEditCtrl" can 
					be used to access the embedded RTF-control. Remember to 
					call "AfxInitRichEdit(2)"!

					The contents can be saved to disk by calling "Save", and 
					loaded from disk by calling "Load". The two functions 
					will automatically display a file dialog if the file 
					name parameter of the calls are left empty.

					"GetRTF" and "SetRTF" can be used to get and set the 
					contents of the embedded RTF-control as RTF 
					respectively.

					The ruler measures can be displayed as inches or 
					centimeters, by calling "SetMode". "GetMode" will get the 
					current mode.

   ========================================================================*/

#include "stdafx.h"
#include "RulerRichEditCtrl.h"
#include "resource.h"
#include "..\3rdparty\TextFile.h"
#include "..\shared\misc.h"
#include "..\shared\enstring.h"

#include "ids.h"
#include <afxpriv.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

const int SCMARGIN = 4;
const LPCTSTR FILEPREFIX = "file://";

/////////////////////////////////////////////////////////////////////////////
// Registered messages for ruler/CRulerRichEditCtrl communication

UINT urm_RULERACTION = ::RegisterWindowMessage(_T("_RULERRICHEDITCTRL_RULER_TRACK_"));
UINT urm_GETSCROLLPOS = ::RegisterWindowMessage(_T("_RULERRICHEDITCTRL_GET_SCROLL_POS_"));
UINT urm_SETCURRENTFONTNAME = ::RegisterWindowMessage(_T("_RULERRICHEDITCTRL_SET_CURRENT_FONT_NAME"));
UINT urm_SETCURRENTFONTSIZE = ::RegisterWindowMessage(_T("_RULERRICHEDITCTRL_SET_CURRENT_FONT_SIZE"));
UINT urm_SETCURRENTFONTCOLOR = ::RegisterWindowMessage(_T("_RULERRICHEDITCTRL_SET_CURRENT_FONT_COLOR"));

/////////////////////////////////////////////////////////////////////////////
// Stream callback functions
// Callbacks to the Save and Load functions.

static DWORD CALLBACK StreamOut(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
{
	CMemFile* pFile = (CMemFile*)dwCookie;

	pFile->Write(pbBuff, cb);
	*pcb = cb;
	
	return 0;
}

static DWORD CALLBACK StreamOutLen(DWORD dwCookie, LPBYTE /*pbBuff*/, LONG cb, LONG *pcb)
{
	int* pLen = (int*)dwCookie;

	*pLen += cb;
	*pcb = cb;
	
	return 0;

}

struct STREAMINCOOKIE
{
	STREAMINCOOKIE(const CString& sContent) : sRTF(sContent), nStreamPos(0) {}

	int GetLength() const { return sRTF.GetLength(); }
	LPCTSTR CopyFrom() const { return ((LPCTSTR)sRTF) + nStreamPos; }

	const CString& sRTF;
	int nStreamPos;
};

static DWORD CALLBACK StreamIn(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
{
	STREAMINCOOKIE* pCookie = (STREAMINCOOKIE*)dwCookie;
	int max = min(cb, pCookie->GetLength());

	strncpy((LPSTR)pbBuff, pCookie->CopyFrom(), max);

	*pcb = max;
	pCookie->nStreamPos += max;

	return 0;

}

/////////////////////////////////////////////////////////////////////////////
BEGIN_MESSAGE_MAP(CRulerRichEditCtrl, CWnd)
	//{{AFX_MSG_MAP(CRulerRichEditCtrl)
	ON_WM_PAINT()
	ON_WM_ERASEBKGND()
	ON_WM_SIZE()
	ON_COMMAND(BUTTON_FONT, OnButtonFont)
	ON_COMMAND(BUTTON_COLOR, OnButtonColor)
	ON_COMMAND(BUTTON_BOLD, OnButtonBold)
	ON_COMMAND(BUTTON_STRIKETHRU, OnButtonStrikethrough)
	ON_COMMAND(BUTTON_ITALIC, OnButtonItalic)
	ON_COMMAND(BUTTON_UNDERLINE, OnButtonUnderline)
	ON_COMMAND(BUTTON_LEFTALIGN, OnButtonLeftAlign)
	ON_COMMAND(BUTTON_CENTERALIGN, OnButtonCenterAlign)
	ON_COMMAND(BUTTON_RIGHTALIGN, OnButtonRightAlign)
	ON_COMMAND(BUTTON_INDENT, OnButtonIndent)
	ON_COMMAND(BUTTON_OUTDENT, OnButtonOutdent)
	ON_COMMAND(BUTTON_BULLET, OnButtonBullet)
	ON_WM_SETFOCUS()
	ON_MESSAGE(WM_SETTEXT, OnSetText)
	ON_MESSAGE(WM_GETTEXT, OnGetText )
	ON_MESSAGE(WM_GETTEXTLENGTH, OnGetTextLength)
	ON_WM_ENABLE()
	ON_REGISTERED_MESSAGE(urm_RULERACTION, OnTrackRuler)
	ON_REGISTERED_MESSAGE(urm_GETSCROLLPOS, OnGetScrollPos)
	ON_REGISTERED_MESSAGE(urm_SETCURRENTFONTNAME, OnSetCurrentFontName)
	ON_REGISTERED_MESSAGE(urm_SETCURRENTFONTSIZE, OnSetCurrentFontSize)
	ON_REGISTERED_MESSAGE(urm_SETCURRENTFONTCOLOR, OnSetCurrentFontColor)
	//}}AFX_MSG_MAP
	ON_COMMAND(BUTTON_TEXTCOLOR, OnButtonTextColor)
	ON_COMMAND(BUTTON_BACKCOLOR, OnButtonBackColor)
	ON_WM_CREATE()
	ON_MESSAGE(WM_SETFONT, OnSetFont)
	ON_EN_HSCROLL(RTF_CONTROL, OnEnHScroll)
	ON_NOTIFY(EN_SELCHANGE, RTF_CONTROL, OnEnSelChange)
	ON_MESSAGE(WM_IDLEUPDATECMDUI, OnUpdateToolbar)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CRulerRichEditCtrl

CRulerRichEditCtrl::CRulerRichEditCtrl() : m_pen(PS_DOT, 0, RGB(0, 0, 0))
/* ============================================================
	Function :		CRulerRichEditCtrl::CRulerRichEditCtrl
	Description :	constructor
	Access :		Public
					
	Return :		void
	Parameters :	none

	Usage :			

   ============================================================*/
{

	m_rulerPosition = 0;
	m_margin = 0;
	m_movingtab = -1;
	m_offset = 0;
	m_readOnly = FALSE;
//	m_richEditModule = LoadLibrary (_T("Riched20.dll"));
	m_bWordWrap = FALSE;
	ShowToolbar();
	ShowRuler();

	m_cfDefault.dwMask = CFM_SIZE | CFM_FACE | CFM_BOLD | CFM_ITALIC | 
						 CFM_UNDERLINE | CFM_STRIKEOUT | CFM_COLOR;
	m_cfDefault.yHeight = 200;
	m_cfDefault.dwEffects = CFE_AUTOBACKCOLOR | CFE_AUTOCOLOR;
	lstrcpy(m_cfDefault.szFaceName, _T("Times New Roman"));

	CUrlRichEditCtrl::SetGotoErrorMsg(CEnString(IDS_COMMENTSGOTOERRMSG));
}

CRulerRichEditCtrl::~CRulerRichEditCtrl()
/* ============================================================
	Function :		CRulerRichEditCtrl::~CRulerRichEditCtrl
	Description :	destructor
	Access :		Public
					
	Return :		void
	Parameters :	none

	Usage :			

   ============================================================*/
{

//	if (m_richEditModule)
//		FreeLibrary (m_richEditModule);

	m_pen.DeleteObject();

}


BOOL CRulerRichEditCtrl::Create(DWORD dwStyle, const RECT &rect, CWnd* pParentWnd, UINT nID, BOOL /*autohscroll*/)
/* ============================================================
	Function :		CRulerRichEditCtrl::Create
	Description :	Creates the control and sub controls.
	Access :		Public
					
	Return :		BOOL				-	"TRUE" if created OK.
	Parameters :	DWORD dwStyle		-	Style of the control, 
											normally "WS_CHILD" 
											and "WS_VISIBLE".
					const RECT &rect	-	Placement rectangle.
					CWnd* pParentWnd	-	Parent window.
					UINT nID			-	Control ID
					BOOL autohscroll	-	"TRUE" if the RTF-control
											should have the 
											"ES_AUTOHSCROLL" style
											set.

	Usage :			Call to create the control.

   ============================================================*/
{

	BOOL result = CWnd::Create(NULL, _T(""), dwStyle, rect, pParentWnd, nID);

	return result;

}

BOOL CRulerRichEditCtrl::CreateToolbar()
/* ============================================================
	Function :		CRulerRichEditCtrl::CreateToolbar
	Description :	Creates the toolbar control
	Access :		Private

	Return :		BOOL	-	"TRUE" if the toolbar was created ok.
	Parameters :	none

	Usage :			Called during control creation

   ============================================================*/
{
	return m_toolbar.Create(this);
}

BOOL CRulerRichEditCtrl::CreateRuler()
/* ============================================================
	Function :		CRulerRichEditCtrl::CreateRuler
	Description :	Creates the ruler control
	Access :		Private

	Return :		BOOL	-	"TRUE" if created ok.
	Parameters :	none

	Usage :			Called during control creation

   ============================================================*/
{

	CRect rect;
	GetClientRect(rect);

	CRect rulerRect(0, TOOLBAR_HEIGHT, rect.right, TOOLBAR_HEIGHT + RULER_HEIGHT);
	return m_ruler.Create(rulerRect, this, RULER_CONTROL);

}

BOOL CRulerRichEditCtrl::CreateRTFControl(BOOL autohscroll)
/* ============================================================
	Function :		CRulerRichEditCtrl::CreateRTFControl
	Description :	Creates the embedded RTF-control.
	Access :		Private
					
	Return :		BOOL				-	"TRUE" if created ok.
	Parameters :	BOOL autohscroll	-	"TRUE" if the RTF-control
											should have the
											"ES_AUTOHSCROLL" style
											set.

	Usage :			Called during control creation

   ============================================================*/
{

	BOOL result = FALSE;

	CRect rect;
	GetClientRect(rect);

	int top = TOOLBAR_HEIGHT + RULER_HEIGHT;
	CRect rtfRect(0, top, rect.right, rect.bottom);
	DWORD style = ES_NOHIDESEL | WS_CHILD | WS_VISIBLE | /*WS_BORDER |*/ WS_HSCROLL | WS_VSCROLL | ES_WANTRETURN | ES_MULTILINE;

	if (autohscroll)
		style |= ES_AUTOHSCROLL;

	if (m_rtf.Create(style, rtfRect, this, RTF_CONTROL))
	{
		// Setting up default tab stops
		ParaFormat para(PFM_TABSTOPS);
		para.cTabCount = MAX_TAB_STOPS;
		for(int t = 0; t < MAX_TAB_STOPS ; t++)
			para.rgxTabs[ t ] = 640 * (t + 1);

		m_rtf.SetParaFormat(para);

		// Setting default character format
		m_rtf.SetDefaultCharFormat(m_cfDefault);

		// Set the internal tabs array
		SetTabStops((LPLONG) (para.rgxTabs), MAX_TAB_STOPS);

		m_rtf.SetEventMask(m_rtf.GetEventMask() | ENM_SELCHANGE | ENM_SCROLL | ENM_CHANGE);
		m_rtf.ModifyStyleEx(0, WS_EX_CLIENTEDGE);

		result = TRUE;
	}

	return result;

}

void CRulerRichEditCtrl::UpdateEditRect()
{
	// Set up edit rect margins
	CRect rc;
	m_rtf.GetClientRect(rc);

	rc.top = SCMARGIN;
	rc.left = SCMARGIN * 2;
	rc.right -= SCMARGIN * 2;

	m_rtf.SetRect(rc);
}

void CRulerRichEditCtrl::CreateMargins()
/* ============================================================
	Function :		CRulerRichEditCtrl::CreateMargins
	Description :	Sets the margins for the subcontrols and 
					the RTF-control edit rect.
	Access :		Private

	Return :		void
	Parameters :	none

	Usage :			Called during control creation.

   ============================================================*/
{
	UpdateEditRect();

	// Get the diff between the window- and client 
	// rect of the RTF-control. This gives the actual 
	// size of the RTF-control border.
	CRect	r1;
	CRect	r2;

	m_rtf.GetWindowRect(r1);
	m_rtf.GetClientRect(r2);
	m_rtf.ClientToScreen(r2);

	// Create the margin for the toolbar 
	// controls and the ruler.
	m_margin = SCMARGIN * 2 + r2.left - r1.left;
	m_ruler.SetMargin(m_margin);

}

/////////////////////////////////////////////////////////////////////////////
// CRulerRichEditCtrl message handlers

int CRulerRichEditCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CWnd::OnCreate(lpCreateStruct) == -1)
		return -1;

	// Save screen resolution for later on.
	CClientDC dc(this);
	m_physicalInch = dc.GetDeviceCaps(LOGPIXELSX);

	// Create sub-controls
	BOOL autohscroll = TRUE;

	if (CreateRTFControl(autohscroll) && CreateToolbar() && CreateRuler())
	{
		CreateMargins();
		SetReadOnly(GetReadOnly()); 
		UpdateToolbarButtons();

		CRect rClient;
		GetClientRect(rClient);

		LayoutControls(rClient.Width(), rClient.Height());

		return 0;
	}

	return -1;
}

void CRulerRichEditCtrl::OnEnHScroll()
{
	m_ruler.Invalidate(FALSE);
	m_ruler.UpdateWindow();
}

void CRulerRichEditCtrl::OnEnSelChange(NMHDR* /*pNMHDR*/, LRESULT* pResult)
{
	// Update the toolbar
	UpdateToolbarButtons();
	
	// Update ruler
	m_ruler.Invalidate(FALSE);
	m_ruler.UpdateWindow();

	*pResult = 0;
}

LRESULT CRulerRichEditCtrl::OnSetFont(WPARAM wp, LPARAM /*lp*/)
{
	// reverse engineer the hFont and use the results
	// for the rtf defaults
	CString sFace;
	int nPoint = Misc::GetFontNameSize((HFONT)wp, sFace);

	if (nPoint && !sFace.IsEmpty())
	{
		// lets have a backup plan
		if (!m_toolbar.SetFontName(sFace))
		{
			sFace = "MS Sans Serif";
			nPoint = 9;
			m_toolbar.SetFontName(sFace);
		}

		m_toolbar.SetFontSize(nPoint);

		// update default char format
		strcpy(m_cfDefault.szFaceName, sFace);
		m_cfDefault.yHeight = nPoint * 20;
		
		m_rtf.SetDefaultCharFormat(m_cfDefault);
	}
	// else eat it

	return 0L;
}

void CRulerRichEditCtrl::OnPaint() 
/* ============================================================
	Function :		CRulerRichEditCtrl::OnPaint
	Description :	Paints the ruler.
	Access :		Protected
					
	Return :		void
	Parameters :	none

	Usage :			Called from MFC. 

   ============================================================*/
{

	CPaintDC mainDC(this);
	UpdateTabStops();

}

BOOL CRulerRichEditCtrl::OnEraseBkgnd(CDC* /*pDC*/) 
/* ============================================================
	Function :		CRulerRichEditCtrl::OnEraseBkgnd
	Description :	Returns "TRUE" to avoid flicker.
	Access :		Protected
					
	Return :		BOOL		-	Always "TRUE",
	Parameters :	CDC* pDC	-	Not used
					
	Usage :			Called from MFC. 

   ============================================================*/
{
	
	return TRUE;

}

BOOL CRulerRichEditCtrl::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) 
/* ============================================================
	Function :		CRulerRichEditCtrl::OnNotify
	Description :	Called as the RTF-control is updated or 
					the selection changes.
	Access :		Protected
					
	Return :		BOOL				-	From base class
	Parameters :	WPARAM wParam		-	Control ID
					LPARAM lParam		-	Not interested
					LRESULT* pResult	-	Not interested
					
	Usage :			Called from MFC. We must check the control 
					every time the selection changes or the 
					contents are changed, as the cursor might 
					have entered a new paragraph, with new tab 
					and/or font settings.

   ============================================================*/
{
	return CWnd::OnNotify(wParam, lParam, pResult);
}

void CRulerRichEditCtrl::OnSize(UINT nType, int cx, int cy) 
/* ============================================================
	Function :		CRulerRichEditCtrl::OnSize
	Description :	We resize the embedded RTF-control.
	Access :		Protected
					
	Return :		void
	Parameters :	UINT nType	-	Not interested
					int cx		-	New width
					int cy		-	New height
					
	Usage :			Called from MFC. 

   ============================================================*/
{

	CWnd::OnSize(nType, cx, cy);
	
	if (m_rtf.m_hWnd)
	{
		UpdateEditRect();
		LayoutControls(cx, cy);

	}
	
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?