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

📄 htricheditctrl.cpp

📁 电驴的源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//this file is part of eMule
//Copyright (C)2002 Merkur ( devs@emule-project.net / http://www.emule-project.net )
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 2 of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "stdafx.h"
#include <share.h>
#include "emule.h"
#include "HTRichEditCtrl.h"
#include "OtherFunctions.h"
#include "Preferences.h"
#include "MenuCmds.h"

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


IMPLEMENT_DYNAMIC(CHTRichEditCtrl, CRichEditCtrl)

BEGIN_MESSAGE_MAP(CHTRichEditCtrl, CRichEditCtrl)
	ON_WM_CONTEXTMENU()
	ON_WM_KEYDOWN()
	ON_WM_PAINT()
	ON_CONTROL_REFLECT(EN_ERRSPACE, OnEnErrspace)
	ON_CONTROL_REFLECT(EN_MAXTEXT, OnEnMaxtext)
	ON_NOTIFY_REFLECT_EX(EN_LINK, OnEnLink)
	ON_WM_CREATE()
	ON_WM_SYSCOLORCHANGE()
END_MESSAGE_MAP()

CHTRichEditCtrl::CHTRichEditCtrl()
{
	m_bRichEdit = true;
	m_bAutoScroll = true;
	m_bNoPaint = false;
	m_bEnErrSpace = false;
	m_bRestoreFormat = false;
	memset(&m_cfDefault, 0, sizeof m_cfDefault);
}

CHTRichEditCtrl::~CHTRichEditCtrl(){
}

void CHTRichEditCtrl::Localize(){
}

void CHTRichEditCtrl::Init(LPCTSTR pszTitle, LPCTSTR pszSkinKey)
{
	SetProfileSkinKey(pszSkinKey);
	SetTitle(pszTitle);

	m_LogMenu.CreatePopupMenu();
	m_LogMenu.AddMenuTitle(GetResString(IDS_LOGENTRY));
	m_LogMenu.AppendMenu(MF_STRING, MP_COPYSELECTED, GetResString(IDS_COPY));
	m_LogMenu.AppendMenu(MF_SEPARATOR);
	m_LogMenu.AppendMenu(MF_STRING, MP_SELECTALL, GetResString(IDS_SELECTALL));
	m_LogMenu.AppendMenu(MF_STRING, MP_REMOVEALL, GetResString(IDS_PW_RESET));
	m_LogMenu.AppendMenu(MF_STRING, MP_SAVELOG, GetResString(IDS_SAVELOG) + _T("..."));
	m_LogMenu.AppendMenu(MF_SEPARATOR);
	m_LogMenu.AppendMenu(MF_STRING, MP_AUTOSCROLL, GetResString(IDS_AUTOSCROLL));

	VERIFY( SendMessage(EM_SETUNDOLIMIT, 0, 0) == 0 );
	int iMaxLogBuff = thePrefs.GetMaxLogBuff();
	if (afxData.bWin95)
		LimitText(iMaxLogBuff > 0xFFFF ? 0xFFFF : iMaxLogBuff);
	else
		LimitText(iMaxLogBuff ? iMaxLogBuff : 128*1024);

	VERIFY( GetSelectionCharFormat(m_cfDefault) );
}

void CHTRichEditCtrl::SetProfileSkinKey(LPCTSTR pszSkinKey)
{
	m_strSkinKey = pszSkinKey;
}

void CHTRichEditCtrl::SetTitle(LPCTSTR pszTitle)
{
	m_strTitle = pszTitle;
}

int CHTRichEditCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CRichEditCtrl::OnCreate(lpCreateStruct) == -1)
		return -1;
	Init(NULL);
	return 0;
}

LRESULT CHTRichEditCtrl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message) {
		case WM_ERASEBKGND:
			if (m_bNoPaint)
				return TRUE;
		case WM_PAINT:
			if (m_bNoPaint)
				return TRUE;
	}
	return CRichEditCtrl::WindowProc(message, wParam, lParam);
}

void CHTRichEditCtrl::FlushBuffer()
{
	if (m_astrBuff.GetSize() > 0){ // flush buffer
		for (int i = 0; i < m_astrBuff.GetSize(); i++)
			AddLine(m_astrBuff[i], m_astrBuff[i].GetLength());
		m_astrBuff.RemoveAll();
	}
}

void CHTRichEditCtrl::AddEntry(LPCTSTR pszMsg)
{
	CString strLine(pszMsg);
	strLine += _T("\n");
	if (m_hWnd == NULL){
		m_astrBuff.Add(strLine);
	}
	else{
		FlushBuffer();
		AddLine(strLine, strLine.GetLength());
	}
}

void CHTRichEditCtrl::Add(LPCTSTR pszMsg, int iLen)
{
	if (m_hWnd == NULL){
		CString strLine(pszMsg);
		m_astrBuff.Add(strLine);
	}
	else{
		FlushBuffer();
		AddLine(pszMsg, iLen);
	}
}

void CHTRichEditCtrl::AddLine(LPCTSTR pszMsg, int iLen, bool bLink, COLORREF cr)
{
	int iMsgLen = (iLen == -1) ? _tcslen(pszMsg) : iLen;
	if (iMsgLen == 0)
		return;
#ifdef _DEBUG
//	if (pszMsg[iMsgLen - 1] == _T('\n'))
//		ASSERT( iMsgLen >= 2 && pszMsg[iMsgLen - 2] == _T('\r') );
#endif

	// Get Edit contents dimensions and cursor position
	long iStartChar, iEndChar;
	GetSel(iStartChar, iEndChar);
	long iSize = GetWindowTextLength();

	if (iStartChar == iSize && iSize == iEndChar)
	{
		// The cursor resides at the end of text
		SCROLLINFO si;
		si.cbSize = sizeof si;
		si.fMask = SIF_ALL;
		if (m_bAutoScroll && GetScrollInfo(SB_VERT, &si) && si.nPos >= (int)(si.nMax - si.nPage + 1))
		{
			// Not scrolled away
			SafeAddLine(iSize, pszMsg, iStartChar, iEndChar, bLink, cr);
			if (m_bAutoScroll && !IsWindowVisible())
				ScrollToLastLine();
		}
		else
		{
			// Reduce flicker by ignoring WM_PAINT
			m_bNoPaint = true;
			BOOL bIsVisible = IsWindowVisible();
			if (bIsVisible)
				SetRedraw(FALSE);

			// Remember where we are
			int nFirstLine = !m_bAutoScroll ? GetFirstVisibleLine() : 0;
		
			// Select at the end of text and replace the selection
			// This is a very fast way to add text to an edit control
			SafeAddLine(iSize, pszMsg, iStartChar, iEndChar, bLink, cr);
			SetSel(iStartChar, iEndChar); // Restore our previous selection

			if (!m_bAutoScroll)
				LineScroll(nFirstLine - GetFirstVisibleLine());
			else
				ScrollToLastLine();

			m_bNoPaint = false;
			if (bIsVisible){
				SetRedraw();
				if (m_bRichEdit)
					Invalidate();
			}
		}
	}
	else
	{
		// We should add the text anyway...

		// Reduce flicker by ignoring WM_PAINT
		m_bNoPaint = true;
		BOOL bIsVisible = IsWindowVisible();
		if (bIsVisible)
			SetRedraw(FALSE);

		// Remember where we are
		//int nFirstLine = !m_bAutoScroll ? GetFirstVisibleLine() : 0;
		POINT ptPos;
		if (!m_bAutoScroll)
			SendMessage(EM_GETSCROLLPOS, 0, (LPARAM)&ptPos);
	
		if (iStartChar != iEndChar)
		{
			// If we are currently selecting some text, we have to find out
			// if the caret is near the beginning of this block or near the end.
			// Note that this does not always work. Because of the EM_CHARFROMPOS
			// message returning only 16 bits this will fail if the user has selected 
			// a block with a length dividable by 64k.

			// NOTE: This may cause a lot of terrible CRASHES within the RichEdit control when used for a RichEdit control!?
			// To reproduce the crash: click in the RE control while it's drawing a line an start a selection!
			if (!m_bRichEdit){
			    CPoint pt;
			    ::GetCaretPos(&pt);
			    int nCaretPos = CharFromPos(pt);
			    if (abs((iStartChar % 0xffff - nCaretPos)) < abs((iEndChar % 0xffff - nCaretPos)))
			    {
				    nCaretPos = iStartChar;
				    iStartChar = iEndChar;
				    iEndChar = nCaretPos;
			    }
		    }
		}

		// Note: This will flicker, if someone has a good idea how to prevent this - let me know
		
		// Select at the end of text and replace the selection
		// This is a very fast way to add text to an edit control
		SafeAddLine(iSize, pszMsg, iStartChar, iEndChar, bLink, cr);
		SetSel(iStartChar, iEndChar); // Restore our previous selection

		if (!m_bAutoScroll){
			//LineScroll(nFirstLine - GetFirstVisibleLine());
			SendMessage(EM_SETSCROLLPOS, 0, (LPARAM)&ptPos);
		}
		else
			ScrollToLastLine();

		m_bNoPaint = false;
		if (bIsVisible){
			SetRedraw();
			if (m_bRichEdit)
				Invalidate();
		}
	}
}

void CHTRichEditCtrl::OnEnErrspace()
{
	m_bEnErrSpace = true;
}

void CHTRichEditCtrl::OnEnMaxtext()
{
	m_bEnErrSpace = true;
}

void CHTRichEditCtrl::ScrollToLastLine()
{
	// WM_VSCROLL does not work correctly under Win98 (or older version of comctl.dll)
	SendMessage(WM_VSCROLL, SB_BOTTOM);
	if (afxData.bWin95){
		// older version of comctl.dll seem to need this to properly update the display
		int iPos = GetScrollPos(SB_VERT);
		SendMessage(WM_VSCROLL, MAKELONG(SB_THUMBPOSITION, iPos));
		SendMessage(WM_VSCROLL, SB_ENDSCROLL);
	}
}

void CHTRichEditCtrl::AddString(int nPos, LPCTSTR pszString, bool bLink, COLORREF cr)
{
	bool bRestoreFormat = false;
	m_bEnErrSpace = false;
	SetSel(nPos, nPos);
	if (bLink)
	{
		CHARFORMAT2 cf;
		memset(&cf, 0, sizeof cf);
		GetSelectionCharFormat(cf);
		cf.dwMask |= CFM_LINK;
		cf.dwEffects |= CFE_LINK;
		SetSelectionCharFormat(cf);
	}
	else if (cr != CLR_DEFAULT)
	{
		CHARFORMAT cf;
		GetSelectionCharFormat(cf);
		cf.dwMask |= CFM_COLOR;
		cf.dwEffects &= ~CFE_AUTOCOLOR;
		cf.crTextColor = cr;
		SetSelectionCharFormat(cf);
		bRestoreFormat = true;
	}
	else if (m_bRestoreFormat)
	{
		SetSelectionCharFormat(m_cfDefault);
	}
	ReplaceSel(pszString);
	m_bRestoreFormat = bRestoreFormat;
}

void CHTRichEditCtrl::SafeAddLine(int nPos, LPCTSTR pszLine, long& iStartChar, long& iEndChar, bool bLink, COLORREF cr)
{
	AddString(nPos, pszLine, bLink, cr);

	if (m_bEnErrSpace)
	{
		bool bOldNoPaint = m_bNoPaint;
		m_bNoPaint = true;
		BOOL bIsVisible = IsWindowVisible();
		if (bIsVisible)
			SetRedraw(FALSE);

		// remove the first line as long as we are capable of adding the new line
		int iSafetyCounter = 0;
		while (m_bEnErrSpace && iSafetyCounter < 10)
		{
			// delete the previous partially added line
			SetSel(nPos, -1);

⌨️ 快捷键说明

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