📄 cdragedit.cpp
字号:
// CDragEdit.cpp : implementation file
//
// Author : Sam Lu
// E-mail : ysl@springsoft.com.tw
//
#include "stdafx.h"
#include "Exam1_1_10.h"
#include "CDragEdit.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define MAXLINELEN 2048
enum {
DE_INSEL, DE_BEFORESEL, DE_AFTERSEL
};
/////////////////////////////////////////////////////////////////////////////
// CDragEdit
CDragEdit::CDragEdit()
{
ms_bDragInit=FALSE;
ms_nEnableFlags=0;
ms_bInDragging=FALSE;
ms_bDropEqualDrag=FALSE;
}
CDragEdit::~CDragEdit()
{
}
BEGIN_MESSAGE_MAP(CDragEdit, CDragEditBase)
//{{AFX_MSG_MAP(CDragEdit)
ON_WM_LBUTTONDOWN()
ON_WM_SETCURSOR()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDragEdit message handlers
BOOL CDragEdit::ms_bOleInit=FALSE;
BOOL CDragEdit::Init(int nFlags)
{
if (!ms_bOleInit) {
if (!AfxOleInit()) {
TRACE("Fail in OLE initialating\n");
return FALSE;
}
ms_bOleInit=TRUE;
}
if (ms_bDragInit) return FALSE;
ms_nEnableFlags=nFlags;
if (!GetSafeHwnd()) {
TRACE("You should create CDragEdit first, before this function is called\n");
return FALSE;
}
if (!ms_dropTarget.Register(this)) {
TRACE("Fail in registing drop target\n");
return FALSE;
}
ms_bDragInit=TRUE;
return TRUE;
}
//we reimpelmented this function for fixing SDK's bug that
//it always returns (-1,-1) when the uChar is the last char
CPoint CDragEdit::PosFromChar(UINT uChar)
{
if (0==uChar)
return CPoint(0,0);
CPoint pt=CDragEditBase::PosFromChar(uChar);
if (pt.x<0 && pt.y<0) {
int nLine, nPos;
_CharToLinePos((int)uChar,&nLine,&nPos);
//get dc and select current using font
CClientDC dc(this);
dc.SelectObject(GetFont());
//get position of previous char
pt=CDragEditBase::PosFromChar(uChar-1);
if (nPos==0) {
//if current char is the first char
//we get the current y from previous y plus font height
CSize szFont=dc.GetTextExtent("A",1);
pt.y+=szFont.cy;
pt.x=0;
}
else {
char szBuf[MAXLINELEN];
GetLine(nLine,szBuf,sizeof(szBuf));
CSize szFont=dc.GetTextExtent(&szBuf[nPos-1],1);
pt.x+=szFont.cx;
}
dc.SelectStockObject(SYSTEM_FONT);
}
return pt;
}
//get line and pos information from current selection range
BOOL CDragEdit::GetCurRange(int& nLine1, int& nPos1, int& nLine2, int& nPos2)
{
//get current selection range
GetSel(nPos1,nPos2);
//and trans. to line, pos
_CharToLinePos(nPos1,&nLine1,&nPos1);
_CharToLinePos(nPos2,&nLine2,&nPos2);
return TRUE;
}
//get line and pos from current cursor position
//return TRUE, if cursor is exactly at a char
//return FALSE, if cursor is at white space area
BOOL CDragEdit::GetLinePosByCursor(int& nLine, int& nPos)
{
CPoint ptCursor;
GetCursorPos(&ptCursor);
ScreenToClient(&ptCursor);
nPos=(int)(short)LOWORD((DWORD)CharFromPos(ptCursor));
if (nPos<0) nPos=0;
_CharToLinePos(nPos,&nLine,&nPos);
//the following codes will check if cusor is at white space area
//get the maximum x of nLine
CPoint ptChar;
ptChar=PosFromChar(LineIndex(nLine)+LineLength(LineIndex(nLine)));
if (ptChar.x<ptCursor.x || ptCursor.x<0)
return FALSE;
return TRUE;
}
//set edit's caret position by current cursor position
BOOL CDragEdit::SetCaretByCursor()
{
//get cursor's position and translate it to client coordinate
CPoint ptCursor;
GetCursorPos(&ptCursor);
ScreenToClient(&ptCursor);
//set caret position
int nChar=(int)LOWORD((DWORD)CharFromPos(ptCursor));
SetSel(nChar,nChar);
return TRUE;
}
BOOL CDragEdit::SetCaret(int nLine, int nPos)
{
int nChar=_LinePosToChar(nLine,nPos);
SetSel(nChar,nChar);
return TRUE;
}
//draw a caret at current cursor position
//this function will not affect the caret position or selection status
BOOL CDragEdit::DrawCaretByCursor()
{
int nLine, nPos;
GetLinePosByCursor(nLine,nPos);
SetCaretPos(GetPosFromLinePos(nLine,nPos));
return TRUE;
}
//test if (nLine,Pos) is within (nLine1,nPos1)~(nLine2,nPos2)
static int LinePosInRange(int nLine, int nPos,
int nLine1, int nPos1,
int nLine2, int nPos2)
{
if (nLine1==nLine2) {//single line selection mark
if (nLine<nLine1) return DE_BEFORESEL;
if (nLine>nLine1) return DE_AFTERSEL;
//nLine==nLine1
if (nPos<nPos1) return DE_BEFORESEL;
if (nPos>nPos2) return DE_AFTERSEL;
}
else { //multi-line selection mark
if (nLine<nLine1) return DE_BEFORESEL;
if (nLine>nLine2) return DE_AFTERSEL;
if (nLine==nLine1 &&
nPos<nPos1) return DE_BEFORESEL;
if (nLine==nLine2 &&
nPos>nPos2) return DE_AFTERSEL;
}
return DE_INSEL;
}
//return TRUE, if cursor is within the selection mark
BOOL CDragEdit::IsInSelRange()
{
int nLine1, nPos1, nLine2, nPos2;
GetCurRange(nLine1,nPos1,nLine2,nPos2);
if (nLine1==nLine2 && nPos1==nPos2) //no selection mark
return FALSE;
int nLine, nPos;
if (!GetLinePosByCursor(nLine,nPos)) //out of selection mark
return FALSE;
return (LinePosInRange(nLine,nPos,nLine1,nPos1,
nLine2,nPos2)==DE_INSEL) ? TRUE : FALSE;
}
BOOL CDragEdit::_GetSelText(CString& str)
{
int nLine1, nPos1, nLine2, nPos2;
GetCurRange(nLine1,nPos1,nLine2,nPos2);
ASSERT(nLine1>=0 && nPos1>=0 && nLine2>=0 && nPos2>=0);
char szBuf[MAXLINELEN];
int nLen;
//single-line selection
if (nLine1==nLine2) {
nLen=GetLine(nLine1,szBuf,sizeof(szBuf));
szBuf[nLen]='\0';
szBuf[nPos2]='\0';
str=szBuf+nPos1;
return TRUE;
}
//multi-line section
nLen=GetLine(nLine1,szBuf,sizeof(szBuf));
szBuf[nLen]='\0';
str=szBuf+nPos1;
for (int i=nLine1+1; i<nLine2; i++) {
str+="\r\n";
nLen=GetLine(i,szBuf,sizeof(szBuf));
szBuf[nLen]='\0';
str+=szBuf;
}
str+="\r\n";
nLen=GetLine(nLine2,szBuf,sizeof(szBuf));
szBuf[nLen]='\0';
szBuf[nPos2]='\0';
str+=szBuf;
return TRUE;
}
void CDragEdit::OnLButtonDown(UINT nFlags, CPoint point)
{
if (!EnableDrag()) {
CDragEditBase::OnLButtonDown(nFlags, point);
return;
}
if (IsInSelRange()) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -