📄 rcveditctrl.cpp
字号:
// RcvEditCtrl.cpp : implementation file
//
//
#include "stdafx.h"
#include "winpsk.h"
#include "winpskdoc.h"
#include "winpskview.h"
#include "RcvView.h"
#include "RcvEditCtrl.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define QUEUE_MOD_MASK 0x00FF
#define ID_TIMER 6
#define RX_ID 0
#define TX_ID -1
/////////////////////////////////////////////////////////////////////////////
// CRcvEditCtrl
CRcvEditCtrl::CRcvEditCtrl()
{
m_LineCount = 0;
m_QHead = 0;
m_QTail = 0;
m_TimerID = 0;
m_LastFont = RX_ID;
m_CTRLKeyDown = FALSE;
m_TXActive = FALSE;
}
CRcvEditCtrl::~CRcvEditCtrl()
{
}
BEGIN_MESSAGE_MAP(CRcvEditCtrl, CRichEditCtrl)
//{{AFX_MSG_MAP(CRcvEditCtrl)
ON_WM_CREATE()
ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
ON_WM_RBUTTONUP()
ON_CONTROL_REFLECT(EN_KILLFOCUS, OnKillfocus)
ON_WM_TIMER()
ON_WM_LBUTTONDBLCLK()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CRcvEditCtrl message handlers
int CRcvEditCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CRichEditCtrl::OnCreate(lpCreateStruct) == -1)
return -1;
m_bUseSlash = FALSE;
return 0;
}
// Initializes the Font, font color, and background color for the
// edit box
void CRcvEditCtrl::SetCharFormat(LOGFONT lf, LOGFONT lfs, COLORREF crText,
COLORREF crSentText,COLORREF crBackground )
{
GetDefaultCharFormat(m_InsertFormat);
m_InsertFormat.cbSize=sizeof(CHARFORMAT);
m_InsertFormat.dwMask = CFM_BOLD|CFM_ITALIC|CFM_UNDERLINE|CFM_STRIKEOUT|
CFM_CHARSET|CFM_COLOR|CFM_FACE|CFM_SIZE;
m_InsertFormat.crTextColor = crText;
m_InsertFormat.yHeight = -lf.lfHeight*20;
m_InsertFormat.bCharSet = lf.lfCharSet;
m_InsertFormat.dwEffects = 0;
if(lf.lfItalic)
m_InsertFormat.dwEffects |= CFE_ITALIC;
if(lf.lfUnderline)
m_InsertFormat.dwEffects |= CFE_UNDERLINE;
if(lf.lfStrikeOut)
m_InsertFormat.dwEffects |= CFE_STRIKEOUT;
if(lf.lfWeight > 500)
m_InsertFormat.dwEffects |= CFE_BOLD;
m_InsertFormat.bPitchAndFamily = lf.lfPitchAndFamily;
strcpy( m_InsertFormat.szFaceName, lf.lfFaceName );
//
GetDefaultCharFormat(m_SentFormat);
m_SentFormat.cbSize=sizeof(CHARFORMAT);
m_SentFormat.dwMask = CFM_BOLD|CFM_ITALIC|CFM_UNDERLINE|CFM_STRIKEOUT|
CFM_CHARSET|CFM_COLOR|CFM_FACE|CFM_SIZE;
m_SentFormat.crTextColor = crSentText;
m_SentFormat.yHeight = -lfs.lfHeight*20;
m_SentFormat.bCharSet = lfs.lfCharSet;
m_SentFormat.dwEffects = 0;
if(lfs.lfItalic)
m_SentFormat.dwEffects |= CFE_ITALIC;
if(lfs.lfUnderline)
m_SentFormat.dwEffects |= CFE_UNDERLINE;
if(lfs.lfStrikeOut)
m_SentFormat.dwEffects |= CFE_STRIKEOUT;
if(lfs.lfWeight > 500)
m_SentFormat.dwEffects |= CFE_BOLD;
m_SentFormat.bPitchAndFamily = lf.lfPitchAndFamily;
strcpy( m_SentFormat.szFaceName, lf.lfFaceName );
SetBackgroundColor( FALSE, crBackground );
SetDefaultCharFormat(m_InsertFormat);
SetSelectionCharFormat(m_InsertFormat);
}
///////////////////////////////////////////////////////////////////////////////
// Message handler when a new character is received and needs to be placed into
// the receive edit box.
///////////////////////////////////////////////////////////////////////////////
void CRcvEditCtrl::OnRcvChar(UINT ch, LONG src)
{
CHARRANGE cr;
if( !PutQue((BYTE)ch) || m_RcvCancel ) //if cancel selection flag is set
{ // or que is full, then need to
m_RcvCancel = FALSE; // deselect any text.
CancelSelection();
}
else
{
GetSel(cr); // if a text selection is made
if( cr.cpMax>cr.cpMin) // then hold off anymore writes to this
{ // edit box for about 10 seconds
if( m_TimerID == 0)
m_TimerID = SetTimer( ID_TIMER, 10000, NULL); //start up timer
return;
}
}
if( m_LastFont != src ) // if font is changing
{
if( src == RX_ID )
{
if( !m_TXActive )
{
SetSelectionCharFormat(m_InsertFormat);
m_LastFont = src;
}
else
{
m_QHead = 0; //clear out any remaining recv chars
m_QTail = 0;
m_LastFont = TX_ID;
}
}
else
{
SetSelectionCharFormat(m_SentFormat);
m_LastFont = src;
}
}
while( CheckQue() ) // if any chars in que send em all to window
{
PutCharInWindow( GetQue() );
}
}
///////////////////////////////////////////////////////////////////////////////
//returns TRUE if there is a character in the receive Queue
///////////////////////////////////////////////////////////////////////////////
BOOL CRcvEditCtrl::CheckQue()
{
return( m_QHead != m_QTail );
}
///////////////////////////////////////////////////////////////////////////////
//returns TRUE if the character is put in the Queue
// returns FALSE if the que is full
///////////////////////////////////////////////////////////////////////////////
BOOL CRcvEditCtrl::PutQue(BYTE ch)
{
INT tmpHead = m_QHead+1;
tmpHead = tmpHead&QUEUE_MOD_MASK;
if( tmpHead == m_QTail )
return FALSE; //que is full
else
m_RcvQue[m_QHead] = ch;
m_QHead = tmpHead;
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
// returns the next character from the queue.
// user must call CheckQue() before calling GetQue().
///////////////////////////////////////////////////////////////////////////////
BYTE CRcvEditCtrl::GetQue()
{
BYTE ch = m_RcvQue[m_QTail];
m_QTail = (m_QTail+1)&QUEUE_MOD_MASK;
return ch;
}
///////////////////////////////////////////////////////////////////////////////
// Places ch into the rich edit window after dealing with backspace, and
// CR LF's and slash zero characters.
///////////////////////////////////////////////////////////////////////////////
void CRcvEditCtrl::PutCharInWindow(BYTE ch)
{
INT TotalLength = GetWindowTextLength();
BYTE temp[3]={0,0,0};
INT cnt = 0;
temp[0] = ch;
if( temp[0] == BACK_SPACE_CODE ) //deal with a backspace character
{
if(TotalLength>1)
{
SetSel(TotalLength-1,TotalLength);
temp[0] = 0;
ReplaceSel( (CHAR*)temp );
}
}
else //here with printable text so put it on screen
{
if( (temp[0] == 0x0D) /*|| (temp[0] == 0x0A)*/ || (temp[0] >= ' ') )
{
if( temp[0] == 0x0D) //CR
temp[1] = 0x0A;
if(temp[0] == '0' && m_bUseSlash)// convert zero to slash zero
temp[0] = (BYTE)216;
SetSel(TotalLength,TotalLength);
ReplaceSel( (CHAR*)temp );
if( (cnt = GetLineCount() ) != m_LineCount)
{
LineScroll(cnt-m_LineCount,0);
m_LineCount = cnt;
}
}
}
}
///////////////////////////////////////////////////////////////////////////////
// Clear the whole edit box
///////////////////////////////////////////////////////////////////////////////
void CRcvEditCtrl::ClearAll()
{
BYTE temp[2]={0,0};
SetSelectionCharFormat(m_InsertFormat);
SetSel(0,-1);
ReplaceSel( (CHAR*)temp );
m_LastFont = TX_ID;
}
///////////////////////////////////////////////////////////////////////////////
// Cancels any text selection
///////////////////////////////////////////////////////////////////////////////
void CRcvEditCtrl::CancelSelection()
{
INT TotalLength = GetWindowTextLength();
if( (TotalLength>1) )
SetSel(TotalLength,TotalLength);
m_RcvCancel = FALSE;
if( m_TimerID == ID_TIMER)
{
KillTimer(m_TimerID);
m_TimerID = 0;
}
}
///////////////////////////////////////////////////////////////////////////////
// Clipboard functions
///////////////////////////////////////////////////////////////////////////////
void CRcvEditCtrl::OnEditCopy()
{
CopyClip();
}
void CRcvEditCtrl::CopyClip()
{
Copy();
m_RcvCancel = TRUE;
//Nasty Casting to set window focus to Xmit window;
((CWinPSKDoc*)((CRcvView*)( (CRcvView*)GetParent() )->
GetDocument()))->m_pXmitEdit->SetFocus();
}
BOOL CRcvEditCtrl::OKCopy()
{
CHARRANGE cr;
GetSel(cr);
return( cr.cpMax>cr.cpMin);
}
///////////////////////////////////////////////////////////////////////////////
// Intercept some key strokes
///////////////////////////////////////////////////////////////////////////////
BOOL CRcvEditCtrl::PreTranslateMessage(MSG* pMsg)
{
CRcvView* pView;
CWinPSKDoc* pDoc;
// If a key is pressed while focus is in the receive edit window,
// pass the key message on to the Xmit window and set focus there too;
if( (pMsg->message == WM_KEYDOWN) || (pMsg->message == WM_SYSKEYDOWN) )
{
switch (pMsg->wParam)
{
case VK_CONTROL: //key exclusions not passed on
m_CTRLKeyDown = TRUE;
break;
default:
if( !m_CTRLKeyDown || ((pMsg->message == WM_SYSKEYDOWN)
&& (pMsg->wParam==VK_F10)))
{
pView = (CRcvView*)GetParent();
ASSERT_VALID(pView);
pDoc = (CWinPSKDoc*)pView->GetDocument();
ASSERT_VALID(pDoc);
pDoc->m_pXmitEdit->PostMessage(pMsg->message ,
pMsg->wParam,
pMsg->lParam);
pDoc->m_pXmitEdit->SetFocus();
POINT Point;
::GetCursorPos(&Point);
::SetCursorPos(Point.x, Point.y);
}
break;
}
}
else
if(pMsg->message == WM_KEYUP)
m_CTRLKeyDown = FALSE;
return CRichEditCtrl::PreTranslateMessage(pMsg);
}
///////////////////////////////////////////////////////////////////////////////
// bring up the clipboard copy menu on right clicks to this edit box
///////////////////////////////////////////////////////////////////////////////
void CRcvEditCtrl::OnRButtonUp(UINT nFlags, CPoint point)
{
CRcvView* pView;
CWinPSKDoc* pDoc;
CHARRANGE cr;
pView = (CRcvView*)GetParent();
ASSERT_VALID(pView);
pDoc = (CWinPSKDoc*)pView->GetDocument();
ASSERT_VALID(pDoc);
CRichEditCtrl::OnRButtonUp(nFlags, point);
if( pDoc->m_pSettings->m_AutoTxtSel)
{
CString str;
GetSel(cr);
if( (cr.cpMax-cr.cpMin) > 1 ) //if selected text is more than one character
{
str = GetSelText();
CancelSelection();
pDoc->m_pTextGrabEdit->InsertCString( str );
}
}
else
{
CMenu Menu;
VERIFY(Menu.LoadMenu(IDR_RCVCLIPMENU));
CMenu* pPopup = Menu.GetSubMenu(0);
// Display the edit copy shortcut menu if anything is selected.
GetSel(cr);
if( cr.cpMax>cr.cpMin)
pPopup->EnableMenuItem(ID_EDIT_COPY, MF_ENABLED|MF_BYCOMMAND);
else
pPopup->EnableMenuItem(ID_EDIT_COPY, MF_GRAYED);
ClientToScreen( &point );
pPopup->TrackPopupMenu( TPM_LEFTALIGN | TPM_RIGHTBUTTON,
point.x, point.y, this);
}
}
//////////////////////////////////////////////////////////////
// Here if someone double clicks in the rx window.
// If it is on a word, it is selected.
//////////////////////////////////////////////////////////////
void CRcvEditCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)
{
CString str;
CRcvView* pView;
CWinPSKDoc* pDoc;
CHARRANGE cr;
CRichEditCtrl::OnLButtonDblClk(nFlags, point);
pView = (CRcvView*)GetParent();
ASSERT_VALID(pView);
pDoc = (CWinPSKDoc*)pView->GetDocument();
ASSERT_VALID(pDoc);
if( pDoc->m_pSettings->m_AutoTxtSel)
{
GetSel(cr);
if( (cr.cpMax-cr.cpMin) > 1 ) //if selected text is more than one character
{
str = GetSelText(); // if any character is numeric, assume is a callsign
if( str.FindOneOf(_T("0123456789\330") ) >= 0 ) // \330 is the slash zero
pDoc->m_pTheirCallEdit->InsertCString( str );
else // else assume a name
pDoc->m_pTheirNameEdit->InsertCString( str );
}
}
}
void CRcvEditCtrl::OnKillfocus()
{
m_RcvCancel = TRUE;
}
///////////////////////////////////////////////////////////////////////////////
// Service selection timeout timer
///////////////////////////////////////////////////////////////////////////////
void CRcvEditCtrl::OnTimer(UINT nIDEvent)
{
if( nIDEvent == m_TimerID )
{
KillTimer(m_TimerID);
m_TimerID = 0;
m_RcvCancel = FALSE; // deselect any text.
CancelSelection();
}
CRichEditCtrl::OnTimer(nIDEvent);
}
///////////////////////////////////////////////////////////////////////////////
// Inserts a time/date stamp in the RX text stream
///////////////////////////////////////////////////////////////////////////////
void CRcvEditCtrl::TXStamp(BOOL m_EchoTXText, BOOL TXStart, BOOL UseLocalTime)
{
CString Preamb;
CString str;
INT cnt;
INT TotalLength = GetWindowTextLength();
CTime time = CTime::GetCurrentTime();
CRcvView* pView;
CWinPSKDoc* pDoc;
pView = (CRcvView*)GetParent();
ASSERT_VALID(pView);
pDoc = (CWinPSKDoc*)pView->GetDocument();
ASSERT_VALID(pDoc);
if(UseLocalTime)
str = time.Format(_T(" - %#d %b %Y %#I:%M:%S %p >>"));
else
str = time.FormatGmt(_T(" - %d %b %Y %H:%M:%S UTC>>"));
if(pDoc->m_pSettings->m_UseSlash)
str.Replace( _T("0") , _T("\330") ); //convert any 0's to slash Zeros
if(m_EchoTXText)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -